summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorondrej.zara <none@none>2008-12-04 08:13:14 +0000
committerondrej.zara <none@none>2008-12-04 08:13:14 +0000
commit3e17dc90adcb2e93d9b3eb5f59adecb1c7981b84 (patch)
tree08d0f7d5f9cc5749e941bdebc63b8f9a2bffd537
parent6bcb4d2789f2524b62a93c85bb3aae8c95d4f902 (diff)
downloadwwwsqldesigner-3e17dc90adcb2e93d9b3eb5f59adecb1c7981b84.zip
wwwsqldesigner-3e17dc90adcb2e93d9b3eb5f59adecb1c7981b84.tar.gz
wwwsqldesigner-3e17dc90adcb2e93d9b3eb5f59adecb1c7981b84.tar.bz2
initial code from release 2.3.1
--HG-- extra : convert_revision : svn%3Ab267cdba-c1da-11dd-874b-8bacd04a0a74/trunk%402
-rw-r--r--backend/php-blank/index.php3
-rw-r--r--backend/php-file/data/default30
-rw-r--r--backend/php-file/index.php35
-rw-r--r--backend/php-mysql/database.sql8
-rw-r--r--backend/php-mysql/index.php192
-rw-r--r--backend/php-sqlite/index.php103
-rw-r--r--backend/php-sqlite/wwwsqldesigner.sqlitebin0 -> 5120 bytes
-rw-r--r--db/mssql/datatypes.xml57
-rw-r--r--db/mssql/output.xsl55
-rw-r--r--db/mysql/datatypes.xml31
-rw-r--r--db/mysql/output.xsl130
-rw-r--r--db/postgresql/datatypes.xml39
-rw-r--r--db/postgresql/output.xsl125
-rw-r--r--db/sqlite/datatypes.xml10
-rw-r--r--db/sqlite/output.xsl88
-rw-r--r--db/web2py/datatypes.xml26
-rw-r--r--db/web2py/output.xsl164
-rw-r--r--doc/index.html344
-rw-r--r--gpl.txt340
-rw-r--r--images/back.gifbin0 -> 64 bytes
-rw-r--r--images/bar_bottom.pngbin0 -> 2947 bytes
-rw-r--r--images/bar_corner.pngbin0 -> 2871 bytes
-rw-r--r--images/bar_left.pngbin0 -> 2887 bytes
-rw-r--r--images/table_bottom.pngbin0 -> 2961 bytes
-rw-r--r--images/table_corner.pngbin0 -> 2893 bytes
-rw-r--r--images/table_right.pngbin0 -> 2989 bytes
-rw-r--r--images/throbber.gifbin0 -> 825 bytes
-rw-r--r--index.html232
-rw-r--r--js/config.js13
-rw-r--r--js/oz.js315
-rw-r--r--js/wwwsqldesigner.js2185
-rw-r--r--locale/cs.xml92
-rw-r--r--locale/de.xml92
-rw-r--r--locale/en.xml92
-rw-r--r--locale/es.xml92
-rw-r--r--locale/fr.xml91
-rw-r--r--locale/pl.xml92
-rw-r--r--locale/pt_BR.xml92
-rw-r--r--styles/doc.css19
-rw-r--r--styles/ie6.css58
-rw-r--r--styles/ie7.css15
-rw-r--r--styles/print.css3
-rw-r--r--styles/style.css229
43 files changed, 5492 insertions, 0 deletions
diff --git a/backend/php-blank/index.php b/backend/php-blank/index.php
new file mode 100644
index 0000000..7777f32
--- /dev/null
+++ b/backend/php-blank/index.php
@@ -0,0 +1,3 @@
+<?php
+ header("HTTP/1.0 501 Not Implemented");
+?>
diff --git a/backend/php-file/data/default b/backend/php-file/data/default
new file mode 100644
index 0000000..a6de8b9
--- /dev/null
+++ b/backend/php-file/data/default
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" ?><sql><datatypes db="mysql">
+ <group label="Numeric" color="rgb(238,238,170)">
+ <type label="Integer" length="0" sql="INTEGER" re="INT" quote=""/>
+ <type label="Decimal" length="1" sql="DECIMAL" re="DEC" quote=""/>
+ <type label="Single precision" length="0" sql="FLOAT" quote=""/>
+ <type label="Double precision" length="0" sql="DOUBLE" re="DOUBLE" quote=""/>
+ </group>
+
+ <group label="Character" color="rgb(255,200,200)">
+ <type label="Char" length="1" sql="CHAR" quote="'"/>
+ <type label="Varchar" length="1" sql="VARCHAR" quote="'"/>
+ <type label="Text" length="0" sql="MEDIUMTEXT" re="TEXT" quote="'"/>
+ <type label="Binary" length="1" sql="BINARY" quote="'"/>
+ <type label="Varbinary" length="1" sql="VARBINARY" quote="'"/>
+ <type label="BLOB" length="0" sql="BLOB" re="BLOB" quote="'"/>
+ </group>
+
+ <group label="Date &amp; Time" color="rgb(200,255,200)">
+ <type label="Date" length="0" sql="DATE" quote="'"/>
+ <type label="Time" length="0" sql="TIME" quote="'"/>
+ <type label="Datetime" length="0" sql="DATETIME" quote="'"/>
+ <type label="Year" length="0" sql="YEAR" quote=""/>
+ <type label="Timestamp" length="0" sql="TIMESTAMP" quote="'"/>
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,200,255)">
+ <type label="ENUM" length="1" sql="ENUM" quote=""/>
+ <type label="SET" length="1" sql="SET" quote=""/>
+ </group>
+</datatypes><table x="50" y="50" name="Producer"><row name="id" null="0" autoincrement="1"><datatype>INTEGER</datatype></row><row name="name" null="1" autoincrement="0"><datatype>VARCHAR(100)</datatype><default>NULL</default></row><key type="PRIMARY" name=""><part>id</part></key></table><table x="574" y="66" name="Consumer"><row name="id" null="0" autoincrement="1"><datatype>INTEGER</datatype></row><row name="name" null="1" autoincrement="0"><datatype>VARCHAR(100)</datatype><default>NULL</default></row><key type="PRIMARY" name=""><part>id</part></key></table><table x="195" y="333" name="Product"><row name="id" null="0" autoincrement="1"><datatype>INTEGER</datatype></row><row name="id_Producer" null="0" autoincrement="1"><datatype>INTEGER</datatype><relation table="Producer" row="id" /></row><row name="name" null="1" autoincrement="0"><datatype>VARCHAR(100)</datatype></row><key type="PRIMARY" name=""><part>id</part></key></table><table x="383" y="227" name="Garbage"><row name="id" null="0" autoincrement="1"><datatype>INTEGER</datatype></row><row name="id_Product" null="0" autoincrement="1"><datatype>INTEGER</datatype><relation table="Product" row="id" /></row><row name="id_Consumer" null="0" autoincrement="1"><datatype>INTEGER</datatype><relation table="Consumer" row="id" /></row><row name="consumed" null="0" autoincrement="0"><datatype>TIMESTAMP</datatype></row><key type="PRIMARY" name=""><part>id</part></key></table></sql> \ No newline at end of file
diff --git a/backend/php-file/index.php b/backend/php-file/index.php
new file mode 100644
index 0000000..054ce47
--- /dev/null
+++ b/backend/php-file/index.php
@@ -0,0 +1,35 @@
+<?php
+ $a = (isset($_GET["action"]) ? $_GET["action"] : false);
+ switch ($a) {
+ case "list":
+ $files = glob("data/*");
+ foreach ($files as $file) {
+ $name = basename($file);
+ echo $name."\n";
+ }
+ break;
+ case "save":
+ $keyword = (isset($_GET["keyword"]) ? $_GET["keyword"] : "");
+ $keyword = "data/".basename($keyword);
+ $f = fopen($keyword, "w");
+ $data = file_get_contents("php://input");
+ if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
+ $data = stripslashes($data);
+ }
+ fwrite($f, $data);
+ fclose($f);
+ header("HTTP/1.0 201 Created");
+ break;
+ case "load":
+ $keyword = (isset($_GET["keyword"]) ? $_GET["keyword"] : "");
+ $keyword = "data/".basename($keyword);
+ if (!file_exists($keyword)) {
+ header("HTTP/1.0 404 Not Found");
+ } else {
+ header("Content-type: text/xml");
+ echo file_get_contents($keyword);
+ }
+ break;
+ default: header("HTTP/1.0 501 Not Implemented");
+ }
+?>
diff --git a/backend/php-mysql/database.sql b/backend/php-mysql/database.sql
new file mode 100644
index 0000000..9bdf1d6
--- /dev/null
+++ b/backend/php-mysql/database.sql
@@ -0,0 +1,8 @@
+DROP TABLE IF EXISTS `wwwsqldesigner`;
+
+CREATE TABLE `wwwsqldesigner` (
+ `keyword` varchar(30) NOT NULL default '',
+ `data` text,
+ `dt` timestamp,
+ PRIMARY KEY (`keyword`)
+);
diff --git a/backend/php-mysql/index.php b/backend/php-mysql/index.php
new file mode 100644
index 0000000..7675ef1
--- /dev/null
+++ b/backend/php-mysql/index.php
@@ -0,0 +1,192 @@
+<?php
+ function setup_saveloadlist() {
+ define("SERVER","localhost");
+ define("USER","");
+ define("PASSWORD","");
+ define("DB","home");
+ define("TABLE","wwwsqldesigner");
+ }
+ function setup_import() {
+ define("SERVER","tv1.dev");
+ define("USER","tvprogram");
+ define("PASSWORD","xxx");
+ define("DB","information_schema");
+ }
+ function connect() {
+ $conn = mysql_connect(SERVER,USER,PASSWORD);
+ if (!$conn) return false;
+ $res = mysql_select_db(DB);
+ if (!$res) return false;
+ return true;
+ }
+
+ function import() {
+ $db = (isset($_GET["database"]) ? $_GET["database"] : "information_schema");
+ $db = mysql_real_escape_string($db);
+ $xml = "";
+
+ $arr = array();
+ @ $datatypes = file("../../db/mysql/datatypes.xml");
+ $arr[] = $datatypes[0];
+ $arr[] = '<sql db="mysql">';
+ for ($i=1;$i<count($datatypes);$i++) {
+ $arr[] = $datatypes[$i];
+ }
+
+ $result = mysql_query("SELECT * FROM TABLES WHERE TABLE_SCHEMA = '".$db."'");
+ while ($row = mysql_fetch_array($result)) {
+ $table = $row["TABLE_NAME"];
+ $xml .= '<table name="'.$table.'">';
+ $comment = (isset($row["TABLE_COMMENT"]) ? $row["TABLE_COMMENT"] : "");
+ if ($comment) { $xml .= '<comment>'.$comment.'</comment>'; }
+
+ $q = "SELECT * FROM COLUMNS WHERE TABLE_NAME = '".$table."' AND TABLE_SCHEMA = '".$db."'";
+ $result2 = mysql_query($q);
+ while ($row = mysql_fetch_array($result2)) {
+ $name = $row["COLUMN_NAME"];
+ $type = $row["COLUMN_TYPE"];
+ $comment = (isset($row["COLUMN_COMMENT"]) ? $row["COLUMN_COMMENT"] : "");
+ $null = ($row["IS_NULLABLE"] == "YES" ? "0" : "1");
+ $def = $row["COLUMN_DEFAULT"];
+ $ai = (preg_match("/auto_increment/i",$row["EXTRA"]) ? "1" : "0");
+ if ($def == "NULL") { $def = ""; }
+ $xml .= '<row name="'.$name.'" null="'.$null.'" autoincrement="'.$ai.'">';
+ $xml .= '<datatype>'.strtoupper($type).'</datatype>';
+ $xml .= '<default>'.$def.'</default>';
+ if ($comment) { $xml .= '<comment>'.$comment.'</comment>'; }
+
+ /* fk constraints */
+ $q = "SELECT
+ REFERENCED_TABLE_NAME AS 'table', REFERENCED_COLUMN_NAME AS 'column'
+ FROM KEY_COLUMN_USAGE k
+ LEFT JOIN TABLE_CONSTRAINTS c
+ ON k.CONSTRAINT_NAME = c.CONSTRAINT_NAME
+ WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
+ AND c.TABLE_SCHEMA = '".$db."' AND c.TABLE_NAME = '".$table."'
+ AND k.COLUMN_NAME = '".$name."'";
+ $result3 = mysql_query($q);
+
+ while ($row = mysql_fetch_array($result3)) {
+ $xml .= '<relation table="'.$row["table"].'" row="'.$row["column"].'" />';
+ }
+
+ $xml .= '</row>';
+ }
+
+ /* keys */
+ $q = "SELECT * FROM STATISTICS WHERE TABLE_NAME = '".$table."' AND TABLE_SCHEMA = '".$db."' ORDER BY SEQ_IN_INDEX ASC";
+ $result2 = mysql_query($q);
+ $idx = array();
+
+ while ($row = mysql_fetch_array($result2)) {
+ $name = $row["INDEX_NAME"];
+ if (array_key_exists($name, $idx)) {
+ $obj = $idx[$name];
+ } else {
+ $type = $row["INDEX_TYPE"];
+ $t = "INDEX";
+ if ($type == "FULLTEXT") { $t = $type; }
+ if ($row["NON_UNIQUE"] == "0") { $t = "UNIQUE"; }
+ if ($name == "PRIMARY") { $t = "PRIMARY"; }
+
+ $obj = array(
+ "columns" => array(),
+ "type" => $t
+ );
+ }
+
+ $obj["columns"][] = $row["COLUMN_NAME"];
+ $idx[$name] = $obj;
+ }
+
+ foreach ($idx as $name=>$obj) {
+ $xml .= '<key name="'.$name.'" type="'.$obj["type"].'">';
+ for ($i=0;$i<count($obj["columns"]);$i++) {
+ $col = $obj["columns"][$i];
+ $xml .= '<part>'.$col.'</part>';
+ }
+ $xml .= '</key>';
+ }
+ $xml .= "</table>";
+ }
+ $arr[] = $xml;
+ $arr[] = '</sql>';
+ return implode("\n",$arr);
+ }
+
+ $a = (isset($_GET["action"]) ? $_GET["action"] : false);
+ switch ($a) {
+ case "list":
+ setup_saveloadlist();
+ if (!connect()) {
+ header("HTTP/1.0 503 Service Unavailable");
+ break;
+ }
+ $result = mysql_query("SELECT keyword FROM ".TABLE." ORDER BY dt DESC");
+ while ($row = mysql_fetch_assoc($result)) {
+ echo $row["keyword"]."\n";
+ }
+ break;
+ case "save":
+ setup_saveloadlist();
+ if (!connect()) {
+ header("HTTP/1.0 503 Service Unavailable");
+ break;
+ }
+ $keyword = (isset($_GET["keyword"]) ? $_GET["keyword"] : "");
+ $keyword = mysql_real_escape_string($keyword);
+ $data = file_get_contents("php://input");
+ if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
+ $data = stripslashes($data);
+ }
+ $data = mysql_real_escape_string($data);
+ $r = mysql_query("SELECT * FROM ".TABLE." WHERE keyword = '".$keyword."'");
+ if (mysql_num_rows($r) > 0) {
+ $res = mysql_query("UPDATE ".TABLE." SET data = '".$data."' WHERE keyword = '".$keyword."'");
+ } else {
+ $res = mysql_query("INSERT INTO ".TABLE." (keyword, data) VALUES ('".$keyword."', '".$data."')");
+ }
+ if (!$res) {
+ header("HTTP/1.0 500 Internal Server Error");
+ } else {
+ header("HTTP/1.0 201 Created");
+ }
+ break;
+ case "load":
+ setup_saveloadlist();
+ if (!connect()) {
+ header("HTTP/1.0 503 Service Unavailable");
+ break;
+ }
+ $keyword = (isset($_GET["keyword"]) ? $_GET["keyword"] : "");
+ $keyword = mysql_real_escape_string($keyword);
+ $result = mysql_query("SELECT `data` FROM ".TABLE." WHERE keyword = '".$keyword."'");
+ $row = mysql_fetch_assoc($result);
+ if (!$row) {
+ header("HTTP/1.0 404 Not Found");
+ } else {
+ header("Content-type: text/xml");
+ echo $row["data"];
+ }
+ break;
+ case "import":
+ setup_import();
+ if (!connect()) {
+ header("HTTP/1.0 503 Service Unavailable");
+ break;
+ }
+
+ header("Content-type: text/xml");
+ echo import();
+ break;
+ default: header("HTTP/1.0 501 Not Implemented");
+ }
+
+
+ /*
+ list: 501/200
+ load: 501/200/404
+ save: 501/201
+ import: 501/200
+ */
+?> \ No newline at end of file
diff --git a/backend/php-sqlite/index.php b/backend/php-sqlite/index.php
new file mode 100644
index 0000000..fa12fed
--- /dev/null
+++ b/backend/php-sqlite/index.php
@@ -0,0 +1,103 @@
+<?php
+ function setup_saveloadlist() {
+ define( "FILE" , "wwwsqldesigner.sqlite" );
+ define( "TABLE" , "wwwsqldesigner" );
+ }
+ function setup_import() {
+ header( 'HTTP/1.0 501 Not Implemented' );
+ die;
+ }
+ function connect() {
+ if( !file_exists( FILE ) ) $initReq = true;
+ $GLOBALS['sqlConnect'] = sqlite_open( FILE , 0666 );
+ if( !$GLOBALS['sqlConnect'] ) return false;
+ if( $initReq ) {
+ $initSQL = "CREATE TABLE wwwsqldesigner (
+ keyword varchar(30) NOT NULL default '',
+ data TEXT ,
+ dt DATETIME DEFAULT CURRENT_TIMESTAMP ,
+ PRIMARY KEY ( keyword )
+ );";
+ $res = sqlite_exec( $initSQL , $GLOBALS['sqlConnect'] );
+ return $res;
+ }
+ return true;
+ }
+ function import() {
+ header( 'HTTP/1.0 501 Not Implemented' );
+ }
+
+ $a = (isset($_GET["action"]) ? $_GET["action"] : false);
+ switch( $a ) {
+ case 'list' :
+ setup_saveloadlist();
+ if( !connect() ) {
+ header( 'HTTP/1.0 503 Service Unavailable' );
+ break;
+ }
+ $result = sqlite_query( "SELECT keyword FROM ".TABLE." ORDER BY dt DESC" , $GLOBALS['sqlConnect'] );
+ if( sqlite_num_rows( $result )>0 ) {
+ while( $row = sqlite_fetch_array( $result ) ) {
+ echo $row['keyword']."\n";
+ }
+ } else {
+ echo "--No Designs Saved";
+ }
+ break;
+ case 'save' :
+ setup_saveloadlist();
+ if( !connect() ) {
+ header( 'HTTP/1.0 503 Service Unavailable' );
+ break;
+ }
+ $keyword = ( isset( $_GET['keyword'] ) ? $_GET['keyword'] : '' );
+ $keyword = sqlite_escape_string( $keyword );
+ $data = file_get_contents( "php://input" );
+ if( get_magic_quotes_gpc()
+ || get_magic_quotes_runtime() ) {
+ $data = stripslashes( $data );
+ }
+ $data = sqlite_escape_string( $data );
+ $r = sqlite_query( "SELECT * FROM ".TABLE." WHERE keyword = '$keyword'" , $GLOBALS['sqlConnect'] );
+ if( sqlite_num_rows($r)>0 ) {
+ $res = sqlite_query( "UPDATE ".TABLE." SET data = '$data' WHERE keyword = '$keyword'" , $GLOBALS['sqlConnect'] );
+ } else {
+ $res = sqlite_query( "INSERT INTO ".TABLE." (keyword, data) VALUES ('$keyword', '$data')" , $GLOBALS['sqlConnect'] );
+ }
+ if( !$res ) {
+ header( 'HTTP/1.0 500 Internal Server Error' );
+ } else {
+ header( 'HTTP/1.0 201 Created' );
+ }
+ break;
+ case 'load' :
+ setup_saveloadlist();
+ if ( !connect() ) {
+ header( 'HTTP/1.0 503 Service Unavailable' );
+ break;
+ }
+ $keyword = ( isset( $_GET['keyword'] ) ? $_GET['keyword'] : '' );
+ $keyword = sqlite_escape_string( $keyword );
+ $result = sqlite_query( "SELECT `data` FROM ".TABLE." WHERE keyword = '$keyword'" , $GLOBALS['sqlConnect'] );
+ $row = sqlite_fetch_array( $result );
+ if( !$row ) {
+ header( 'HTTP/1.0 404 Not Found' );
+ } else {
+ header( 'Content-type: text/xml' );
+ echo $row['data'];
+ }
+ break;
+ case 'import' :
+ setup_import();
+ default:
+ header( 'HTTP/1.0 501 Not Implemented' );
+ }
+
+
+ /*
+ list: 501/200
+ load: 501/200/404
+ save: 501/201
+ import: 501/200
+ */
+?> \ No newline at end of file
diff --git a/backend/php-sqlite/wwwsqldesigner.sqlite b/backend/php-sqlite/wwwsqldesigner.sqlite
new file mode 100644
index 0000000..4ac1255
--- /dev/null
+++ b/backend/php-sqlite/wwwsqldesigner.sqlite
Binary files differ
diff --git a/db/mssql/datatypes.xml b/db/mssql/datatypes.xml
new file mode 100644
index 0000000..6dddbe5
--- /dev/null
+++ b/db/mssql/datatypes.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+ MsSQL XML Datatypes for WWW SQL Designer v 2.x
+ Version: 0.1
+ Author: schliden@gmail.com
+-->
+<datatypes db="mssql">
+ <group label="Integer" color="rgb(238,238,170)">
+ <type label="TinyInt" length="0" sql="tinyint" re="INT" quote="" bytes="1" note="Integer data: 0 to 255" />
+ <type label="SmallInt" length="0" sql="smallint" re="INT" quote="" bytes="2" note="Integer data: -32,768 to 32,767" />
+ <type label="Int" length="0" sql="int" re="INT" quote="" bytes="4" note="Integer data: -2,147,483,648 to 2,147,483,647" />
+ <type label="BigInt" length="0" sql="bigint" re="INT" quote="" bytes="8" note="Integer data: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807" />
+ </group>
+
+ <group label="Monetary" color="rgb(238,238,170)">
+ <type label="Money" length="0" sql="money" re="FLOAT" quote="" bytes="8" note="Integer data: -922,337,203,685,477.5808 to 922,337,203,685,477.5807" />
+ <type label="SmallMoney" length="0" sql="smallmoney" re="FLOAT" quote="" bytes="4" note="-214,748.3648 to 214,748.3647" />
+ </group>
+
+ <group label="Numeric" color="rgb(238,238,170)">
+ <type label="Real" length="0" sql="real" re="FLOAT" quote="" bytes="4" note="Floating precision number data: -3.402823E+38 to 3.402823E+38" />
+ <type label="Float" length="0" sql="float" re="FLOAT" quote="" bytes="8" note="Floating precision number data: -4.94E+324 to 4.94E+324" />
+ <type label="Decimal" length="1" sql="decimal" re="DEC" quote="" bytes="n*" note="Fixed precision and scale numeric data: -10^38 +1 to 10^38 -1 (decimal and numeric are synonyms)" />
+ <type label="Numeric" length="1" sql="numeric" re="DEC" quote="" bytes="n*" note="Fixed precision and scale numeric data: -10^38 +1 to 10^38 -1 (decimal and numeric are synonyms)" />
+ </group>
+
+ <group label="Character" color="rgb(255,200,200)">
+ <type label="Char" length="0" sql="char" quote="'" bytes="n" note="Fixed-length character data with a maximum length of 8,000 characters" />
+ <type label="Varchar" length="1" sql="varchar" quote="'" bytes="m &lt;= n" note="Variable-length data with a maximum of 8,000 characters" />
+ <type label="Text" length="1" sql="text" quote="'" bytes="&lt;= 2,147,483,647" note="Variable-length data with a maximum length of 2,147,483,647 characters" />
+ </group>
+
+ <group label="Unicode Character" color="rgb(255,200,200)">
+ <type label="nChar" length="0" sql="nchar" quote="'" bytes="n" note="Fixed-length Unicode data with a maximum length of 4,000 characters" />
+ <type label="nVarchar" length="1" sql="nvarchar" quote="'" bytes="m &lt;= n" note="Variable-length Unicode data with a maximum length of 4,000 characters" />
+ <type label="nText" length="1" sql="ntext" quote="'" bytes="&lt;= 2,147,483,647" note="Variable-length Unicode data with a maximum length of 1,073,741,823 characters" />
+ </group>
+
+
+ <group label="Date &amp; Time" color="rgb(200,255,200)">
+ <type label="Datetime" length="0" sql="datetime" quote="" bytes="8" note="Jan 1, 1753 to Dec 31, 9999" />
+ <type label="SmallDateTime" length="0" sql="smalldatetime" quote="" bytes="4" note="Jan 1, 1900 to Dec 31, 2079" />
+ </group>
+
+ <group label="Binary" color="rgb(200,200,255)">
+ <type label="Binary" length="0" sql="binary" quote="'" bytes="n" note="Fixed-length binary data with a maximum length of 8,000 bytes" />
+ <type label="Varbinary" length="1" sql="varbinary" quote="'" bytes="m &lt;= n" note="Variable-length binary data with a maximum length of 8,000 bytes" />
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,220,255)">
+ <type label="Bit" length="0" sql="bit" quote="" bytes="1" note="Boolean: 1 or 0" />
+ <type label="Image" length="1" sql="image" re="BLOB" quote="" bytes="0 to 2,147,483,647" note="Variable-length binary data with a maximum length of 2,147,483,647 bytes" />
+ <type label="Timestamp" length="0" sql="timestamp" quote="" bytes="8" note="Locally unique binary number updated as a row gets updated" />
+ <type label="SQL Variant" length="1" sql="sql_variant" quote="" bytes="" note="Stores any datatype except text, ntext, image, timestamp" />
+ <type label="Uniqueidentifier" length="1" sql="uniqueidentifier" quote="" bytes="16" note="GUID" />
+ </group>
+</datatypes>
diff --git a/db/mssql/output.xsl b/db/mssql/output.xsl
new file mode 100644
index 0000000..6be4953
--- /dev/null
+++ b/db/mssql/output.xsl
@@ -0,0 +1,55 @@
+<?xml version="1.0" ?>
+<!--
+ XML 2 MsSQL XSL transformation for WWW SQL Designer v 2.x
+ Version: 0.1
+ Author: schliden@gmail.com
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+<xsl:template match="/sql">
+
+<!-- tables -->
+ <xsl:for-each select="table">
+ <xsl:text>CREATE TABLE [</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>] (
+</xsl:text>
+ <xsl:for-each select="row">
+ <xsl:text> [</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>] </xsl:text>
+
+ <xsl:value-of select="datatype" />
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="@null = 0">
+ <xsl:text>NOT NULL </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="@autoincrement = 1">
+ <xsl:text>IDENTITY (1, 1) </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="not (position()=last())">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+
+ <xsl:if test="comment">
+ <xsl:text> -- </xsl:text><xsl:value-of select="comment" />
+ </xsl:if>
+
+ <xsl:if test="not (position()=last())">
+ <xsl:text>
+</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:text>
+) ON [PRIMARY]
+GO
+
+</xsl:text>
+
+ </xsl:for-each>
+</xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/db/mysql/datatypes.xml b/db/mysql/datatypes.xml
new file mode 100644
index 0000000..ea0600a
--- /dev/null
+++ b/db/mysql/datatypes.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<datatypes db="mysql">
+ <group label="Numeric" color="rgb(238,238,170)">
+ <type label="Integer" length="0" sql="INTEGER" re="INT" quote="" />
+ <type label="Decimal" length="1" sql="DECIMAL" re="DEC" quote="" />
+ <type label="Single precision" length="0" sql="FLOAT" quote="" />
+ <type label="Double precision" length="0" sql="DOUBLE" re="DOUBLE" quote="" />
+ </group>
+
+ <group label="Character" color="rgb(255,200,200)">
+ <type label="Char" length="1" sql="CHAR" quote="'"/>
+ <type label="Varchar" length="1" sql="VARCHAR" quote="'"/>
+ <type label="Text" length="0" sql="MEDIUMTEXT" re="TEXT" quote="'"/>
+ <type label="Binary" length="1" sql="BINARY" quote="'"/>
+ <type label="Varbinary" length="1" sql="VARBINARY" quote="'"/>
+ <type label="BLOB" length="0" sql="BLOB" re="BLOB" quote="'"/>
+ </group>
+
+ <group label="Date &amp; Time" color="rgb(200,255,200)">
+ <type label="Date" length="0" sql="DATE" quote="'" />
+ <type label="Time" length="0" sql="TIME" quote="'" />
+ <type label="Datetime" length="0" sql="DATETIME" quote="'" />
+ <type label="Year" length="0" sql="YEAR" quote="" />
+ <type label="Timestamp" length="0" sql="TIMESTAMP" quote="'" />
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,200,255)">
+ <type label="ENUM" length="1" sql="ENUM" quote="" />
+ <type label="SET" length="1" sql="SET" quote="" />
+ </group>
+</datatypes>
diff --git a/db/mysql/output.xsl b/db/mysql/output.xsl
new file mode 100644
index 0000000..b0c3e59
--- /dev/null
+++ b/db/mysql/output.xsl
@@ -0,0 +1,130 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+
+<xsl:template name="replace-substring">
+ <xsl:param name="value" />
+ <xsl:param name="from" />
+ <xsl:param name="to" />
+ <xsl:choose>
+ <xsl:when test="contains($value,$from)">
+ <xsl:value-of select="substring-before($value,$from)" />
+ <xsl:value-of select="$to" />
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="substring-after($value,$from)" />
+ <xsl:with-param name="from" select="$from" />
+ <xsl:with-param name="to" select="$to" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value" />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="/sql">
+
+<!-- tables -->
+ <xsl:for-each select="table">
+ <xsl:text>CREATE TABLE `</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>` (
+</xsl:text>
+ <xsl:for-each select="row">
+ <xsl:text>`</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>` </xsl:text>
+
+ <xsl:value-of select="datatype" />
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="@null = 0">
+ <xsl:text>NOT NULL </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="@autoincrement = 1">
+ <xsl:text>AUTO_INCREMENT </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="default">
+ <xsl:text>DEFAULT </xsl:text>
+ <xsl:value-of select="default" />
+ <xsl:text> </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="comment">
+ <xsl:text>COMMENT '</xsl:text>
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="comment" />
+ <xsl:with-param name="from" select='"&apos;"' />
+ <xsl:with-param name="to" select='"&apos;&apos;"' />
+ </xsl:call-template>
+ <xsl:text>' </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="not (position()=last())">
+ <xsl:text>,
+</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+
+<!-- keys -->
+ <xsl:for-each select="key">
+ <xsl:text>,
+</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@type = 'PRIMARY'">PRIMARY KEY (</xsl:when>
+ <xsl:when test="@type = 'FULLTEXT'">FULLTEXT KEY (</xsl:when>
+ <xsl:when test="@type = 'UNIQUE'">UNIQUE KEY (</xsl:when>
+ <xsl:otherwise>KEY (</xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:for-each select="part">
+ <xsl:text>`</xsl:text><xsl:value-of select="." /><xsl:text>`</xsl:text>
+ <xsl:if test="not (position() = last())">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+
+ </xsl:for-each>
+
+ <xsl:text>
+)</xsl:text>
+
+ <xsl:if test="comment">
+ <xsl:text> COMMENT '</xsl:text>
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="comment" />
+ <xsl:with-param name="from" select='"&apos;"' />
+ <xsl:with-param name="to" select='"&apos;&apos;"' />
+ </xsl:call-template>
+ <xsl:text>'</xsl:text>
+ </xsl:if>
+
+ <xsl:text>;
+
+</xsl:text>
+
+ </xsl:for-each>
+
+<!-- fk -->
+ <xsl:for-each select="table">
+ <xsl:for-each select="row">
+ <xsl:for-each select="relation">
+ <xsl:text>ALTER TABLE `</xsl:text>
+ <xsl:value-of select="../../@name" />
+ <xsl:text>` ADD FOREIGN KEY (</xsl:text>
+ <xsl:value-of select="../@name" />
+ <xsl:text>) REFERENCES `</xsl:text>
+ <xsl:value-of select="@table" />
+ <xsl:text>` (`</xsl:text>
+ <xsl:value-of select="@row" />
+ <xsl:text>`);
+</xsl:text>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+
+</xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/db/postgresql/datatypes.xml b/db/postgresql/datatypes.xml
new file mode 100644
index 0000000..138fce7
--- /dev/null
+++ b/db/postgresql/datatypes.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<datatypes db="postgresql">
+ <group label="Numeric" color="rgb(238,238,170)">
+ <type label="Integer" length="0" sql="INTEGER" re="INT" quote="" />
+ <type label="Small Integer" length="0" sql="SMALLINT" quote="" />
+ <type label="Big Integer" length="0" sql="BIGINT" quote="" />
+ <type label="Decimal" length="1" sql="DECIMAL" re="numeric" quote="" />
+ <type label="Serial" length="0" sql="SERIAL" re="SERIAL4" quote="" />
+ <type label="Big Serial" length="0" sql="BIGSERIAL" re="SERIAL8" quote="" />
+ <type label="Real" length="0" sql="BIGINT" quote="" />
+ <type label="Single precision" length="0" sql="FLOAT" quote="" />
+ <type label="Double precision" length="0" sql="DOUBLE" re="DOUBLE" quote="" />
+ </group>
+
+ <group label="Character" color="rgb(255,200,200)">
+ <type label="Char" length="1" sql="CHAR" quote="'"/>
+ <type label="Varchar" length="1" sql="VARCHAR" re="CHARACTER VARYING" quote="'"/>
+ <type label="Text" length="0" sql="TEXT" quote="'"/>
+ <type label="Binary" length="1" sql="BYTEA" quote="'"/>
+ <type label="Boolean" length="0" sql="BOOLEAN" quote="'"/>
+ </group>
+
+ <group label="Date &amp; Time" color="rgb(200,255,200)">
+ <type label="Date" length="0" sql="DATE" quote="'" />
+ <type label="Time" length="1" sql="TIME" quote="'" />
+ <type label="Time w/ TZ" length="0" sql="TIME WITH TIMEZONE" quote="'" />
+ <type label="Interval" length="1" sql="INTERVAL" quote="'" />
+ <type label="Timestamp" length="1" sql="TIMESTAMP" quote="'" />
+ <type label="Timestamp w/ TZ" length="0" sql="TIMESTAMP WITH TIMEZONE" quote="'" />
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,200,255)">
+ <type label="XML" length="1" sql="XML" quote="'" />
+ <type label="Bit" length="1" sql="BIT" quote="'" />
+ <type label="Bit Varying" length="1" sql="VARBIT" re="BIT VARYING" quote="'" />
+ <type label="Inet Host Addr" length="0" sql="INET" quote="'" />
+ <type label="Inet CIDR Addr" length="0" sql="CIDR" quote="'" />
+ </group>
+</datatypes>
diff --git a/db/postgresql/output.xsl b/db/postgresql/output.xsl
new file mode 100644
index 0000000..0b7828e
--- /dev/null
+++ b/db/postgresql/output.xsl
@@ -0,0 +1,125 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+
+<xsl:template name="replace-substring">
+ <xsl:param name="value" />
+ <xsl:param name="from" />
+ <xsl:param name="to" />
+ <xsl:choose>
+ <xsl:when test="contains($value,$from)">
+ <xsl:value-of select="substring-before($value,$from)" />
+ <xsl:value-of select="$to" />
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="substring-after($value,$from)" />
+ <xsl:with-param name="from" select="$from" />
+ <xsl:with-param name="to" select="$to" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value" />
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="/sql">
+
+<!-- tables -->
+ <xsl:for-each select="table">
+ <xsl:text>CREATE TABLE "</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>" (
+</xsl:text>
+ <xsl:for-each select="row">
+ <xsl:text>"</xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text>" </xsl:text>
+
+ <xsl:value-of select="datatype" />
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="@null = 0">
+ <xsl:text>NOT NULL </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="default">
+ <xsl:text>DEFAULT </xsl:text>
+ <xsl:value-of select="default" />
+ <xsl:text> </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="comment">
+ <xsl:text>/* COMMENT '</xsl:text>
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="comment" />
+ <xsl:with-param name="from" select='"&apos;"' />
+ <xsl:with-param name="to" select='"&apos;&apos;"' />
+ </xsl:call-template>
+ <xsl:text>' */</xsl:text>
+ </xsl:if>
+
+ <xsl:if test="not (position()=last())">
+ <xsl:text>,
+</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+
+<!-- keys -->
+ <xsl:for-each select="key">
+ <xsl:text>,
+</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@type = 'PRIMARY'">PRIMARY KEY (</xsl:when>
+ <xsl:when test="@type = 'UNIQUE'">UNIQUE (</xsl:when>
+ <xsl:otherwise>KEY (</xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:for-each select="part">
+ <xsl:text>"</xsl:text><xsl:value-of select="." /><xsl:text>"</xsl:text>
+ <xsl:if test="not (position() = last())">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+
+ </xsl:for-each>
+
+ <xsl:text>
+)</xsl:text>
+
+ <xsl:if test="comment">
+ <xsl:text> /* </xsl:text>
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="comment" />
+ <xsl:with-param name="from" select='"&apos;"' />
+ <xsl:with-param name="to" select='"&apos;&apos;"' />
+ </xsl:call-template>
+ <xsl:text>*/</xsl:text>
+ </xsl:if>
+
+ <xsl:text>;
+
+</xsl:text>
+
+ </xsl:for-each>
+
+<!-- fk -->
+ <xsl:for-each select="table">
+ <xsl:for-each select="row">
+ <xsl:for-each select="relation">
+ <xsl:text>ALTER TABLE "</xsl:text>
+ <xsl:value-of select="../../@name" />
+ <xsl:text>" ADD FOREIGN KEY (</xsl:text>
+ <xsl:value-of select="../@name" />
+ <xsl:text>) REFERENCES "</xsl:text>
+ <xsl:value-of select="@table" />
+ <xsl:text>" ("</xsl:text>
+ <xsl:value-of select="@row" />
+ <xsl:text>");
+</xsl:text>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+
+</xsl:template>
+</xsl:stylesheet>
diff --git a/db/sqlite/datatypes.xml b/db/sqlite/datatypes.xml
new file mode 100644
index 0000000..5079b3c
--- /dev/null
+++ b/db/sqlite/datatypes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<datatypes db="sqlite">
+ <group label="Affinity">
+ <type label="Text" default="" length="1" sql="TEXT" quote="'" color="rgb(255,200,200)" />
+ <type label="Numeric" default="0" length="0" sql="NUMERIC" quote="" color="rgb(238,238,170)" />
+ <type label="Integer" default="0" length="0" sql="INTEGER" quote="" color="rgb(238,238,170)" />
+ <type label="Real" default="0" length="0" sql="REAL" quote="" color="rgb(238,238,170)" />
+ <type label="None" default="" length="0" sql="NONE" quote="" color="rgb(200,255,200)" />
+ </group>
+</datatypes>
diff --git a/db/sqlite/output.xsl b/db/sqlite/output.xsl
new file mode 100644
index 0000000..7a2857d
--- /dev/null
+++ b/db/sqlite/output.xsl
@@ -0,0 +1,88 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+<xsl:template match="/sql">
+
+<!-- tables -->
+ <xsl:for-each select="table">
+ <xsl:text>CREATE TABLE </xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text> (
+</xsl:text>
+ <xsl:for-each select="row">
+ <xsl:value-of select="@name" />
+ <xsl:text> </xsl:text>
+
+ <xsl:value-of select="datatype" />
+ <xsl:text> </xsl:text>
+
+ <xsl:if test="@null = 0">
+ <xsl:text>NOT NULL </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="@autoincrement = 1">
+ <xsl:text>AUTOINCREMENT </xsl:text>
+ </xsl:if>
+
+ <xsl:if test="default">
+ <xsl:text>DEFAULT </xsl:text>
+ <xsl:value-of select="default" />
+ </xsl:if>
+
+ <xsl:if test="not (position()=last())">
+ <xsl:text>,
+</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+
+<!-- keys -->
+ <xsl:for-each select="key">
+ <xsl:if test="@type = 'PRIMARY' or @type = 'UNIQUE'">
+ <xsl:text>,
+</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@type = 'PRIMARY'">PRIMARY KEY (</xsl:when>
+ <xsl:when test="@type = 'UNIQUE'">UNIQUE (</xsl:when>
+ </xsl:choose>
+
+ <xsl:for-each select="part">
+ <xsl:value-of select="." />
+ <xsl:if test="not (position() = last())">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ </xsl:if>
+
+ </xsl:for-each>
+
+ <xsl:text>
+);
+
+</xsl:text>
+
+ </xsl:for-each>
+
+<!-- fk -->
+ <xsl:for-each select="table">
+ <xsl:for-each select="key">
+ <xsl:if test="@type = 'INDEX'">
+ <xsl:text>CREATE INDEX </xsl:text>
+ <xsl:value-of select="@name" />
+ <xsl:text> ON </xsl:text>
+ <xsl:value-of select="../@name" />
+ <xsl:text> (</xsl:text>
+ <xsl:for-each select="part">
+ <xsl:value-of select="." />
+ <xsl:if test="not (position() = last())">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>);
+</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+
+</xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/db/web2py/datatypes.xml b/db/web2py/datatypes.xml
new file mode 100644
index 0000000..22f2252
--- /dev/null
+++ b/db/web2py/datatypes.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<datatypes db="web2py">
+ <group label="Numeric" color="rgb(238,238,170)">
+ <type label="Integer" length="1" sql="integer" re="INTEGER" quote=""/>
+ <type label="Double precision" length="1" sql="double" re="DOUBLE" quote=""/>
+ </group>
+
+ <group label="Character" color="rgb(255,200,200)">
+ <type label="String" length="1" sql="string" quote="'"/>
+ <type label="Text" length="1" sql="text" quote="'"/>
+ <type label="BLOB" length="1" sql="blob" quote="'"/>
+ </group>
+
+ <group label="Date &amp; Time" color="rgb(200,255,200)">
+ <type label="Date" length="0" sql="date" quote="'"/>
+ <type label="Time" length="0" sql="time" quote="'"/>
+ <type label="Datetime" length="0" sql="datetime" quote="'"/>
+ <type label="Timestamp" length="0" sql="timestamp" quote="'"/>
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,200,255)">
+ <type label="Boolean" length="0" sql="boolean" quote=""/>
+ <type label="Upload" length="0" sql="upload" quote="'"/>
+ <type label="Password" length="0" sql="password" quote="'"/>
+ </group>
+</datatypes> \ No newline at end of file
diff --git a/db/web2py/output.xsl b/db/web2py/output.xsl
new file mode 100644
index 0000000..a94ed99
--- /dev/null
+++ b/db/web2py/output.xsl
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="us-ascii"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="text"/>
+ <!-- this code is not used in template but anyway it can be used someday so i left it to be ;)-->
+ <xsl:template name="replace-substring">
+ <xsl:param name="value"/>
+ <xsl:param name="from"/>
+ <xsl:param name="to"/>
+ <xsl:choose>
+ <xsl:when test="contains($value,$from)">
+ <xsl:value-of select="substring-before($value,$from)"/>
+ <xsl:value-of select="$to"/>
+ <xsl:call-template name="replace-substring">
+ <xsl:with-param name="value" select="substring-after($value,$from)"/>
+ <xsl:with-param name="from" select="$from"/>
+ <xsl:with-param name="to" select="$to"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- return length of element-->
+ <xsl:template name="getsize">
+ <xsl:param name="invalue"/>
+ <xsl:choose>
+ <xsl:when test="contains($invalue,'(')">
+ <xsl:variable name="part" select="substring-after($invalue,'(')"/>
+ <xsl:value-of select="substring-before($part,')')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="/sql">
+ <xsl:text>"""
+just copy paste this code into your model and replace dbOBJECT to something
+you prefer or what is used in your code, another thing that should be known is that
+this code still cannot distinguish what exactly should be in reference title - name
+when you use generic appadmin so please remove all fiealds you don't need not require
+"""
+"""
+database class object creation
+"""
+dbOBJECT = SQLDB("sqlite://dbOBJECT.db")
+</xsl:text>
+ <xsl:for-each select="table">
+ <xsl:text>
+"""
+Table definition
+"""
+dbOBJECT.define_table("</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>",</xsl:text>
+ <xsl:for-each select="row">
+ <xsl:choose>
+ <xsl:when test="not(@name = 'id')">
+ <xsl:text>
+ SQLField("</xsl:text>
+ <xsl:choose>
+ <xsl:when test="not (relation)">
+ <xsl:value-of select="@name"/>
+ <xsl:text>", </xsl:text>
+ <!--<xsl:value-of select="datatype"/>-->
+ <xsl:choose>
+ <xsl:when test="contains(datatype,'(')">
+ <xsl:text>"</xsl:text>
+ <xsl:value-of select="substring-before(datatype,'(')"/>
+ <xsl:text>", length=</xsl:text>
+ <xsl:call-template name="getsize">
+ <xsl:with-param name="invalue" select="datatype"/>
+ </xsl:call-template>
+ <xsl:text>, </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>"</xsl:text>
+ <xsl:value-of select="datatype"/>
+ <xsl:text>", </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@null = 0">
+ <xsl:text>notnull=True, </xsl:text>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="default">
+ <xsl:text>default='</xsl:text>
+ <xsl:value-of select="default"/>
+ <xsl:text>'</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>default=None</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ <xsl:text>", dbOBJECT.</xsl:text>
+ <xsl:for-each select="relation">
+ <xsl:value-of select="@table"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="not (@name = 'id')">
+ <xsl:text>)</xsl:text>
+ </xsl:if>
+ <xsl:if test="not (position()=last())">
+ <xsl:if test="not (@name = 'id')">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <!-- keys -->
+ <!-- maybe something else except unique??-->
+ <xsl:for-each select="key">
+ <xsl:choose>
+ <xsl:when test="@type = 'UNIQUE'">unique=True</xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ <xsl:text>
+
+</xsl:text>
+ </xsl:for-each>
+<!-- fk -->
+<xsl:text>
+"""
+Relations between tables (remove fields you don't need from requires)
+"""
+</xsl:text>
+<!--
+dbOBJECT.druga.prva_id.requires=IS_IN_DB(dbOBJECT, 'prva.id')
+-->
+ <xsl:for-each select="table">
+ <xsl:for-each select="row">
+ <xsl:for-each select="relation">
+ <xsl:variable name="tablename"><xsl:value-of select="@table"/></xsl:variable>
+ <xsl:text>dbOBJECT.</xsl:text>
+ <xsl:value-of select="../../@name"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="../@name"/>
+ <xsl:text>.requires=IS_IN_DB(</xsl:text>
+ <xsl:text>dbOBJECT, '</xsl:text>
+ <xsl:value-of select="@table"/>
+ <xsl:text>.id</xsl:text><!-- hardcoded as this is expected from web2py every table to have anyway :) -->
+ <xsl:for-each select="//table"><!-- have to do this way to find our table->row->names-->
+ <xsl:if test="@name = $tablename">
+ <xsl:for-each select="row">
+ <xsl:if test="not(@name = 'id')">
+ <xsl:text>','</xsl:text>
+ <xsl:value-of select="$tablename"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>')
+</xsl:text>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..179c0c9
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,344 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <link rel="stylesheet" href="../styles/doc.css" type="text/css" />
+ <title>WWW SQL Designer - Documentation</title>
+</head>
+<body>
+<h1>WWW SQL Designer - Documentation</h1>
+
+<h2>Table of contents</h2>
+
+<ul>
+ <li><a href="#usage">Usage</a>
+ <ul>
+ <li><a href="#browsers">Browsers</a></li>
+ <li><a href="#basics">Basics</a></li>
+ </ul>
+ </li>
+ <li><a href="#installation">Installation</a></li>
+ <li><a href="#customization">Customization</a>
+ <ul>
+ <li><a href="#css">CSS</a></li>
+ <li><a href="#locale">Locale</a></li>
+ <li><a href="#databases">Databases</a></li>
+ <li><a href="#backends">Backends</a></li>
+ </ul>
+ </li>
+ <li><a href="#contact">Contact</a></li>
+ <li><a href="#changelog">Changelog</a></li>
+</ul>
+
+<hr/>
+
+<h2><a name="usage">Usage</a></h2>
+<p>Hello and welcome to WWW SQL Designer documentation. This page will hopefully help you with understanding
+how WWW SQL Desginer works and how can it be tailored to suit your needs.</p>
+
+<h3><a name="browsers">Browsers</a></h3>
+
+<p>WWW SQL Designer was tested in the following browsers:</p>
+
+<ul>
+ <li>Firefox 2.x</li>
+ <li>Firefox 3.x</li>
+ <li>Internet Explorer 6</li>
+ <li>Internet Explorer 7</li>
+ <li>Internet Explorer 8</li>
+ <li>Safari 3</li>
+ <li>Opera 9.x</li>
+ <li>Konqueror 3.5.x</li>
+</ul>
+
+<p>Konqueror is the only browser (from this list) which lacks support for Smooth connectors and XSLT
+transformations (generation of SQL scripts).</p>
+
+<h3><a name="basics">Basics</a></h3>
+
+<p>The application allows you to:</p>
+
+<ol>
+ <li>Draw E-R designs</li>
+ <li>Edit tables and rows</li>
+ <li>Manage keys</li>
+ <li>Create relations (FK constraints)</li>
+ <li>Save &amp; Load designs</li>
+ <li>Import DB schemas</li>
+</ol>
+
+<p>Most commands are intuitively available from the right sidebar. Some tasks are described below.</p>
+
+<p>To <strong>drag a table</strong>, press mouse button while pointing at table header. You can then move the
+table around the canvas.</p>
+
+<p>To <strong>edit table properties</strong>, either double-click its heading, or select it and
+then press 'Edit table' button in sidebar.</p>
+
+<p>To <strong>edit field properties</strong>, either double-click it, or select it and
+then press 'Edit field' button in sidebar.</p>
+
+<p>To <strong>manage keys for a table</strong>, select a table and press 'Edit keys' button in sidebar.</p>
+
+<p>To <strong>draw a connector (relation)</strong>, first select a field which forms a Primary Key. Then click 'Create foreign key' button
+in sidebar and click target table's heading. New field and relation will be created.</p>
+
+<p>To <strong>perform any kind of save/load/export/import task</strong>, press the 'Save/Load' button in sidebar.
+A dialog window will appear, allowing you to perform clientside or serverside tasks.</p>
+
+<hr/>
+
+<h2><a name="installation">Installation</a></h2>
+<p>You will need to install WWW SQL Designer if you want to:</p>
+<ul>
+ <li>Use custom locale</li>
+ <li>Use custom CSS file</li>
+ <li>Use custom DB definition</li>
+ <li>Use custom server backend</li>
+</ul>
+
+<p>Just download and unpack latest application archive. There are generally no requirements, but to use
+server-side storage, one should have a working webserver.</p>
+
+<hr/>
+
+<h2><a name="customization">Customization</a></h2>
+
+<p>Many aspects of WWW SQL Designer can be customized and enhanced.
+If you manage to create a new locale / db / backend, feel free to send it to me. I will include your feature
+in a distribution archive.</p>
+
+<h3><a name="css">CSS</a></h3>
+
+<p>Visual properties of the application can be tuned by editing files in <code>css/</code> subdirectory.</p>
+
+<h3><a name="locale">Locale</a></h3>
+
+<p>Locales can be edited and added in <code>locale/</code> subdirectory. New locales must be also registered in
+<code>js/config.js</code>.</p>
+
+<h3><a name="databases">Databases</a></h3>
+
+<p>Supported databases (their datatypes and XSLT template) are stored in <code>db/</code> subdirectory.
+Each database has a datatype definition file (<code>datatypes.xml</code>) and a XSL transformation
+(<code>output.xsl</code>). New databases must be also registered in
+<code>js/config.js</code>.</p></p>
+
+<h3><a name="backends">Backends</a></h3>
+
+<p>Serverside backends allow you to save, load, list and import DB designs. They are written in a serverside
+scripting language and communicate via HTTP requests. Backends are stored in <code>backend/</code> subdirectory.
+A brief summary of backend API follows:</p>
+
+<ul>
+ <li><h4>Saving</h4>
+ <p><strong>Request: </strong> POST <code>?action=save&amp;keyword=somename</code>, XML data contained in POST body<br/>
+ <strong>Valid responses: </strong>HTTP/201 Created, HTTP/500 Internal Server Error, HTTP/503 Service Unavailable</p>
+ </li>
+ <li><h4>Loading</h4>
+ <p><strong>Request: </strong> GET <code>?action=load&amp;keyword=somename</code><br/>
+ <strong>Valid responses: </strong>HTTP/200 OK (loaded XML in response body), HTTP/404 Not Found, HTTP/503 Service Unavailable</p>
+ </li>
+ <li><h4>Listing</h4>
+ <p><strong>Request: </strong> GET <code>?action=list</code><br/>
+ <strong>Valid responses: </strong>HTTP/200 OK (list of available designs separated by newlines in response body), HTTP/503 Service Unavailable</p>
+ </li>
+ <li><h4>Importing</h4>
+ <p><strong>Request: </strong> GET <code>?action=import</code><br/>
+ <strong>Valid responses: </strong>HTTP/200 OK (imported data in response body), HTTP/503 Service Unavailable</p>
+ </li>
+</ul>
+
+<p>For every action mentioned, the backend may also return HTTP/501 Not Implemented, meaning that this action is not supported by the backend.</p>
+<hr/>
+
+<h2><a name="contact">Contact</a></h2>
+
+<p>This tool was created by <a href="http://ondras.zarovi.cz/">Ondrej Zara</a>, &copy; 2005-2008.
+It is released under GNU GPL licence.</p>
+
+<hr/>
+
+<h2><a name="changelog">Changelog</a></h2>
+
+<ul id="changelog">
+ <li>Version 2.3.1 (29.11.2008)
+ <ul>
+ <li>* unix newlines</li>
+ <li>* fixed FK button disabled state synchronization</li>
+ <li>* fixed Spanish translation (Cristián Pérez)</li>
+ </ul>
+ </li>
+
+ <li>Version 2.3 (18.11.2008)
+ <ul>
+ <li>* small typo in sample php-file</li>
+ <li>* comments escaping bugfix (Suzanne Dolberg)</li>
+ <li>+ better French translation (Olivier M)</li>
+ <li>+ PostgreSQL support (Michael Tesch)</li>
+ <li>* bugfix in MSSQL datatypes</li>
+ <li>* updated to oz.js 1.1</li>
+ </ul>
+ </li>
+
+ <li>Version 2.2 (25.9.2008)
+ <ul>
+ <li>+ php-sqlite DB backend (Luke Stevenson)</li>
+ <li>+ web2py (Boris Manojlovic) and MSSQL (Sean) datatype definitions</li>
+ <li>+ Polish (Damian Jaroszewski), Spanish (Rubén Rodríguez Zepeda) and Brazilian (Paulo Marcelo) translation</li>
+ <li>* updated to oz.js 1.04</li>
+ </ul>
+ </li>
+
+ <li>Version 2.1.1 (18.7.2008)
+ <ul>
+ <li>* space after DEFAULT statement in MySQL (Patrice Ferlet, Guillaume Paton)</li>
+ <li>+ escaping apostrophes in COMMENT statements in MySQL (Patrice Ferlet, Guillaume Paton)</li>
+ <li>* better use of custom event</li>
+ <li>* updated to oz.js 1.03</li>
+ </ul>
+ </li>
+
+ <li>Version 2.1 (28.6.2008)
+ <ul>
+ <li>+ "note" attribute for datatypes (Sean)</li>
+ <li>+ French, German and Czech localization (DerHeiko, Laurent Goussard)</li>
+ <li>+ design name in document title (DerHeiko)</li>
+ <li>* updated to oz.js 1.02</li>
+ </ul>
+ </li>
+
+ <li>Version 2.0.1 (1.4.2008)
+ <ul>
+ <li>* no AUTOINCREMENT for foreign keys</li>
+ <li>* changed minimap color for selected table</li>
+ <li>* correct layering of minimap tables</li>
+ </ul>
+ </li>
+
+ <li>Version 2.0 (28.3.2008)
+ <ul>
+ <li>* rewritten from scratch</li>
+ <li>+ smooth connectors</li>
+ <li>+ key management</li>
+ <li>+ custom locales, backends, dbs</li>
+ <li>+ cookies</li>
+ <li>+ much much more</li>
+ </ul>
+ </li>
+
+ <li>--- OBSOLETE BELOW ---</li>
+
+ <li>Version 1.4.1 (13.1.2008)
+ <ul>
+ <li>* languages: Italian, Dutch, Traditional Chinese (Marc, Tiberti Fabio, Finjon Kiang)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.4 (25.11.2007)
+ <ul>
+ <li>* improvements from Travis Kroh: PDO-based io.php, SQLite, Symphony, XSLT for MySQL export, changed order of FK names</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.6 (28.10.2007)
+ <ul>
+ <li>* FK inherits more features from PK (thanks to Cyril Zekser)</li>
+ <li>* Fix for import from MSSQL (thanks to Andrea)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.5 (5.10.2007)
+ <ul>
+ <li>* FK FK inherits datatype from PK (thanks to Kevin T. Ryan)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.4 (24.9.2007)
+ <ul>
+ <li>* two bugfixes for IE7</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.3 (27.7.2007)
+ <ul>
+ <li>* foreign Keys have editable names (revert to previous behavior)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.2 (20.7.2007)
+ <ul>
+ <li>* patches from Tobias Stechbarth</li>
+ <li>* MEDIUMTEXT used for data storage (thanks to Areski)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3.1 (30.5.2007)
+ <ul>
+ <li>* numerous new translations</li>
+ </ul>
+ </li>
+
+ <li>Version 1.3 (6.2.2007)
+ <ul>
+ <li>* browser crash fix (thanks to Hiroki Yoshioka)</li>
+ <li>* importing existing DB schema (not in demo)</li>
+ <li>* Brazilian Portugese (Fabio Gomes Ramos)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.2.1 (31.1.2007)
+ <ul>
+ <li>* PROPEL xslt update (Dominic Pelletier)</li>
+ <li>* Default language fix (Andrej Kvasnica)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.2 (21.1.2007)
+ <ul>
+ <li>* XSLT template to PROPEL xml (Dominic Pelletier)</li>
+ <li>* patched MSSQL template (Romain Fevre)</li>
+ <li>* localisation (Romain Fevre)</li>
+ <li>* Oracle support (Romain Fevre)</li>
+ <li>* CHAR and DECIMAL support (Romain Fevre)</li>
+ </ul>
+ </li>
+
+ <li>Version 1.1.8 (27.11.2006)
+ <ul>
+ <li>* patches from Alex Petrescu</li>
+ </ul>
+ </li>
+
+ <li>Version 1.1.7 (26.10.2006)
+ <ul>
+ <li>* xml2postgresql template, thanks to Gérard</li>
+ <li>* print view, thanks to Tor Edvardsson</li>
+ <li>* Listing of keywords, thanks to Tor Edvardsson</li>
+ <li>* xml2mssql template for creating Microsoft SQL scripts, thanks to Sean</li>
+ <li>* direct loading of saved schema, see FAQ</li>
+ <li>* php script resistant to magic_quotes_gpc</li>
+ </ul>
+ </li>
+
+ <li>Version 1.0 (3.10.2005)
+ <ul>
+ <li>* IE hack instead of an old &amp; ugly solution, thanks to Drew Diller</li>
+ <li>* mouse wheel scrolls minimap, thanks to Andreas Attemann</li>
+ <li>* new Settings button, does nothing :)</li>
+ <li>* more straightforward labels in i/o select</li>
+ <li>* ajax based on xmlhttp, not &lt;script&gt;</li>
+ <li>* bugfix - bad row order when exporting</li>
+ <li>* bugfix - string lengths not exported</li>
+ <li>* xslt tranformation now DIRECTLY IN BROWSER!</li>
+ <li>* button 'clear tables'</li>
+ <li>* optimized bar for lower resolutions</li>
+ <li>* major webpage changes</li>
+ <li>* all styling now in STYLES subdirectory</li>
+ <li>* changed descriptive texts on bar into &lt;label&gt;s</li>
+ <li>* fixed non-selectable user-added rows (thanks to Paul Thrasher)</li>
+ <li>* added GNU GPL licence</li>
+ </ul>
+ </li>
+</ul>
+</body>
diff --git a/gpl.txt b/gpl.txt
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/gpl.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/images/back.gif b/images/back.gif
new file mode 100644
index 0000000..0e93eaa
--- /dev/null
+++ b/images/back.gif
Binary files differ
diff --git a/images/bar_bottom.png b/images/bar_bottom.png
new file mode 100644
index 0000000..bb361ee
--- /dev/null
+++ b/images/bar_bottom.png
Binary files differ
diff --git a/images/bar_corner.png b/images/bar_corner.png
new file mode 100644
index 0000000..807c65c
--- /dev/null
+++ b/images/bar_corner.png
Binary files differ
diff --git a/images/bar_left.png b/images/bar_left.png
new file mode 100644
index 0000000..ec7f34b
--- /dev/null
+++ b/images/bar_left.png
Binary files differ
diff --git a/images/table_bottom.png b/images/table_bottom.png
new file mode 100644
index 0000000..0890c8e
--- /dev/null
+++ b/images/table_bottom.png
Binary files differ
diff --git a/images/table_corner.png b/images/table_corner.png
new file mode 100644
index 0000000..e5e86de
--- /dev/null
+++ b/images/table_corner.png
Binary files differ
diff --git a/images/table_right.png b/images/table_right.png
new file mode 100644
index 0000000..0f4600f
--- /dev/null
+++ b/images/table_right.png
Binary files differ
diff --git a/images/throbber.gif b/images/throbber.gif
new file mode 100644
index 0000000..cce32f2
--- /dev/null
+++ b/images/throbber.gif
Binary files differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..01e7d8a
--- /dev/null
+++ b/index.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+ WWW SQL Designer, (C) 2005-2008 Ondra Zara, ondras@zarovi.cz
+ Version: 2.3.1
+ See gpl.txt for licencing information.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
+<head>
+ <title>WWW SQL Designer</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="styles/style.css" media="all" />
+ <!--[if IE 6]><link rel="stylesheet" type="text/css" href="styles/ie6.css" /><![endif]-->
+ <!--[if IE 7]><link rel="stylesheet" type="text/css" href="styles/ie7.css" /><![endif]-->
+ <link rel="stylesheet" href="styles/print.css" type="text/css" media="print" />
+ <script type="text/javascript" src="js/oz.js"></script>
+ <script type="text/javascript" src="js/config.js"></script>
+ <script type="text/javascript" src="js/wwwsqldesigner.js"></script>
+</head>
+
+<body>
+ <div id="area"></div>
+ <div id="bar">
+ <div class="shadow-left"></div>
+ <div class="shadow-corner"></div>
+ <div class="shadow-bottom"></div>
+
+ <input type="button" id="saveload" />
+
+ <hr/>
+
+ <input type="button" id="addtable" />
+ <input type="button" id="edittable" />
+ <input type="button" id="tablekeys" />
+ <input type="button" id="removetable" />
+ <input type="button" id="aligntables" />
+ <input type="button" id="cleartables" />
+
+ <hr/>
+
+ <input type="button" id="addrow" />
+ <input type="button" id="editrow" />
+ <input type="button" id="uprow" class="small" /><input type="button" id="downrow" class="small"/>
+ <input type="button" id="foreigncreate" />
+ <input type="button" id="removerow" />
+
+ <hr/>
+
+ <input type="button" id="options" />
+ <a href="doc/" target="_blank"><input type="button" id="docs" value="" /></a>
+ </div>
+
+ <div id="minimap"></div>
+
+ <div id="background"></div>
+
+ <div id="window">
+ <div id="windowtitle"><img id="throbber" src="images/throbber.gif" alt="" title=""/></div>
+ <div id="windowcontent"></div>
+ <input type="button" id="windowok" />
+ <input type="button" id="windowcancel" />
+ </div>
+
+ <div id="opts">
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ * <label id="language" for="optionlocale"></label>
+ </td>
+ <td>
+ <select id="optionlocale"></select>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ * <label id="db" for="optiondb"></label>
+ </td>
+ <td>
+ <select id="optiondb"></select>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label id="snap" for="optionsnap"></label>
+ </td>
+ <td>
+ <input type="text" size="4" id="optionsnap" />
+ <span class="small" id="optionsnapnotice"></span>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label id="pattern" for="optionpattern"></label>
+ </td>
+ <td>
+ <input type="text" size="6" id="optionpattern" />
+ <span class="small" id="optionpatternnotice"></span>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label id="hide" for="optionhide"></label>
+ </td>
+ <td>
+ <input type="checkbox" id="optionhide" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ * <label id="vector" for="optionvector"></label>
+ </td>
+ <td>
+ <input type="checkbox" id="optionvector" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <hr />
+
+ * <span class="small" id="optionsnotice"></span>
+ </div>
+
+ <div id="io">
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <fieldset>
+ <legend id="client"></legend>
+ <input type="button" id="clientsave" />
+ <input type="button" id="clientload" />
+ <hr/>
+ <input type="button" id="clientsql" />
+ </fieldset>
+ </td>
+ <td>
+ <fieldset>
+ <legend id="server"></legend>
+ <label for="backend" id="backendlabel"></label> <select id="backend"></select>
+ <hr/>
+ <input type="button" id="serversave" />
+ <input type="button" id="serverload" />
+ <input type="button" id="serverlist" />
+ <input type="button" id="serverimport" />
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <fieldset>
+ <legend id="output"></legend>
+ <textarea id="textarea"></textarea>
+ </fieldset>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div id="keys">
+ <fieldset>
+ <legend id="keyslistlabel"></legend>
+ <select id="keyslist"></select>
+ <input type="button" id="keyadd" />
+ <input type="button" id="keyremove" />
+ </fieldset>
+ <fieldset>
+ <legend id="keyedit"></legend>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <label for="keytype" id="keytypelabel"></label>
+ <select id="keytype"></select>
+ </td>
+ <td></td>
+ <td>
+ <label for="keyname" id="keynamelabel"></label>
+ <input type="text" id="keyname" size="10" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3"><hr/></td>
+ </tr>
+ <tr>
+ <td>
+ <label for="keyfields" id="keyfieldslabel"></label><br/>
+ <select id="keyfields" size="5" multiple="multiple"></select>
+ </td>
+ <td>
+ <input type="button" id="keyleft" value="&lt;&lt;" /><br/>
+ <input type="button" id="keyright" value="&gt;&gt;" /><br/>
+ </td>
+ <td>
+ <label for="keyavail" id="keyavaillabel"></label><br/>
+ <select id="keyavail" size="5" multiple="multiple"></select>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ </div>
+
+ <div id="table">
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <label id="tablenamelabel" for="tablename"></label>
+ </td>
+ <td>
+ <input id="tablename" type="text" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label id="tablecommentlabel" for="tablecomment"></label>
+ </td>
+ <td>
+ <textarea rows="5" cols="40" id="tablecomment"></textarea>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <script type="text/javascript">
+ var d = new SQL.Designer();
+ </script>
+</body>
+</html>
diff --git a/js/config.js b/js/config.js
new file mode 100644
index 0000000..6149d69
--- /dev/null
+++ b/js/config.js
@@ -0,0 +1,13 @@
+var CONFIG = {
+ AVAILABLE_DBS:["mysql","sqlite","web2py","mssql","postgresql"],
+ DEFAULT_DB:"mysql",
+
+ AVAILABLE_LOCALES:["en","fr","de","cs","pl","pt_BR","es"],
+ DEFAULT_LOCALE:"en",
+
+ AVAILABLE_BACKENDS:["php-mysql","php-blank","php-file","php-sqlite"],
+ DEFAULT_BACKEND:["php-mysql"],
+
+ RELATION_THICKNESS:2,
+ RELATION_SPACING:15
+}
diff --git a/js/oz.js b/js/oz.js
new file mode 100644
index 0000000..e3a567c
--- /dev/null
+++ b/js/oz.js
@@ -0,0 +1,315 @@
+/* (c) 2008 Ondrej Zara, 1.1 */
+var OZ = {
+ $:function(x) { return typeof(x) == "string" ? document.getElementById(x) : x; },
+ opera:!!window.opera,
+ ie:!!document.attachEvent && !window.opera,
+ gecko:!!document.getAnonymousElementByAttribute,
+ webkit:!!navigator.userAgent.match(/webkit/i),
+ khtml:!!navigator.userAgent.match(/khtml/i) || !!navigator.userAgent.match(/konqueror/i),
+ Event:{
+ _id:0,
+ _cache:{},
+ _standard:["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","keypress","keydown","keyup",
+ "load","unload","abort","error","resize","scroll","select","change","submit","reset","focus","blur"],
+ add:function(elm,event,cb) {
+ var id = OZ.Event._id++;
+ var element = OZ.$(elm);
+ var fnc = cb;
+ if (OZ.Event._standard.indexOf(event) != -1) {
+ if (document.addEventListener) {
+ element.addEventListener(event,fnc,false);
+ } else if (document.attachEvent) {
+ fnc = function() { return cb.apply(elm,arguments); }
+ element.attachEvent("on"+event,fnc);
+ } else { return false; }
+ }
+ OZ.Event._cache[id] = [element,event,fnc];
+ return id;
+ },
+ remove:function(id) {
+ var e = OZ.Event._cache[id];
+ if (!e) { return; }
+ if (OZ.Event._standard.indexOf(e[1]) != -1) {
+ if (document.removeEventListener) {
+ e[0].removeEventListener(e[1],e[2],false);
+ } else if (document.detachEvent) {
+ e[0].detachEvent("on"+e[1],e[2]);
+ }
+ }
+ delete OZ.Event._cache[id];
+ },
+ stop:function(e) { e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; },
+ prevent:function(e) { e.preventDefault ? e.preventDefault() : e.returnValue = false; },
+ target:function(e) { return e.target || e.srcElement; }
+ },
+ Class:function() {
+ var c = function() {
+ var init = arguments.callee.prototype.init;
+ if (init) { init.apply(this,arguments); }
+ };
+ c.inherit = function(parent) {
+ for (var p in parent.prototype) { this.prototype[p] = parent.prototype[p]; }
+ return this;
+ };
+ c.extend = function(parent) {
+ var tmp = function(){};
+ tmp.prototype = parent.prototype;
+ this.prototype = new tmp();
+ return this;
+ };
+ c.prototype.bind = function(fnc) {
+ var obj = this;
+ return function() {
+ return fnc.apply(obj,arguments);
+ }
+ };
+ c.prototype.dispatch = function(type, data) {
+ var obj = {
+ type:type,
+ target:this,
+ timeStamp:(new Date()).getTime(),
+ data:data
+ }
+ var tocall = [];
+ for (var p in OZ.Event._cache) {
+ var item = OZ.Event._cache[p];
+ if (item[1] == type && (!item[0] || item[0] == this)) { tocall.push(item[2]); }
+ }
+ var len = tocall.length;
+ for (var i=0;i<len;i++) { tocall[i](obj); }
+ }
+ return c;
+ },
+ DOM:{
+ elm:function(name, opts) {
+ var elm = document.createElement(name);
+ for (var p in opts) {
+ var val = opts[p];
+ if (p == "class") { p = "className"; }
+ if (p in elm) { elm[p] = val; }
+ }
+ OZ.Style.set(elm, opts);
+ return elm;
+ },
+ text:function(str) { return document.createTextNode(str); },
+ clear:function(node) { while (node.firstChild) {node.removeChild(node.firstChild);} },
+ pos:function(elm) { /* relative to _viewport_ */
+ var cur = OZ.$(elm);
+ var html = cur.ownerDocument.documentElement;
+ var parent = cur.parentNode;
+ var x = y = 0;
+ if (cur == html) { return [x,y]; }
+ while (1) {
+ if (OZ.Style.get(cur,"position") == "fixed") {
+ x += cur.offsetLeft;
+ y += cur.offsetTop;
+ return [x,y];
+ }
+
+ if (OZ.opera && (parent == html || OZ.Style.get(cur,"display") != "block")) { } else {
+ x -= parent.scrollLeft;
+ y -= parent.scrollTop;
+ }
+ if (parent == cur.offsetParent || cur.parentNode == html) {
+ x += cur.offsetLeft;
+ y += cur.offsetTop;
+ cur = parent;
+ }
+
+ if (parent == html) { return [x,y]; }
+ parent = parent.parentNode;
+ }
+ },
+ scroll:function() {
+ var x = document.documentElement.scrollLeft || document.body.scrollLeft || 0;
+ var y = document.documentElement.scrollTop || document.body.scrollTop || 0;
+ return [x,y];
+ },
+ win:function() {
+ var node = (document.compatMode == "CSS1Compat" ? document.documentElement : document.body);
+ if (OZ.opera && parseFloat(navigator.appVersion) < 9.5) { node = document.body; }
+ var x = node.clientWidth;
+ var y = node.clientHeight;
+ return [x,y];
+ },
+ hasClass:function(node,className) {
+ var arr = OZ.$(node).className.toString().split(" ");
+ return (arr.indexOf(className) != -1);
+ },
+ addClass:function(node,className) {
+ if (OZ.DOM.hasClass(node,className)) { return; }
+ var arr = OZ.$(node).className.toString().split(" ");
+ arr.push(className);
+ OZ.$(node).className = arr.join(" ");
+ },
+ removeClass:function(node,className) {
+ if (!OZ.DOM.hasClass(node,className)) { return; }
+ var arr = OZ.$(node).className.toString().split(" ").filter(function($){ return $ != className; });
+ OZ.$(node).className = arr.join(" ");
+ },
+ append:function() {
+ if (arguments.length == 1) {
+ var arr = arguments[0];
+ var root = OZ.$(arr[0]);
+ for (var i=1;i<arr.length;i++) { root.appendChild(OZ.$(arr[i])); }
+ } else for (var i=0;i<arguments.length;i++) { OZ.DOM.append(arguments[i]); }
+ }
+ },
+ Style:{
+ get:function(elm, prop) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ try {
+ var cs = elm.ownerDocument.defaultView.getComputedStyle(elm,"");
+ } catch(e) {
+ return false;
+ }
+ if (!cs) { return false; }
+ return cs[prop];
+ } else {
+ return elm.currentStyle[prop];
+ }
+ },
+ set:function(elm, obj) {
+ for (var p in obj) {
+ var val = obj[p];
+ if (p == "opacity" && OZ.ie) {
+ p = "filter";
+ val = "alpha(opacity="+Math.round(100*val)+")";
+ elm.style.zoom = 1;
+ } else if (p == "float") {
+ p = (OZ.ie ? "styleFloat" : "cssFloat");
+ }
+ if (p in elm.style) { elm.style[p] = val; }
+ }
+ }
+ },
+ Request:function(url, callback, options) {
+ var o = {data:false, method:"get", headers:{}, xml:false}
+ for (var p in options) { o[p] = options[p]; }
+ o.method = o.method.toUpperCase();
+
+ var xhr = false;
+ if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); }
+ else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
+ else { return false; }
+ xhr.open(o.method, url, true);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState != 4) { return; }
+ if (!callback) { return; }
+ var data = (o.xml ? xhr.responseXML : xhr.responseText);
+ var headers = {};
+ var h = xhr.getAllResponseHeaders();
+ if (h) {
+ h = h.split(/[\r\n]/);
+ for (var i=0;i<h.length;i++) if (h[i]) {
+ var v = h[i].match(/^([^:]+): *(.*)$/);
+ headers[v[1]] = v[2];
+ }
+ }
+ callback(data,xhr.status,headers);
+ };
+ if (o.method == "POST") { xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); }
+ for (var p in o.headers) { xhr.setRequestHeader(p,o.headers[p]); }
+ xhr.send(o.data || null);
+ return xhr;
+ }
+}
+
+if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function(item, from) {
+ var len = this.length;
+ var i = from || 0;
+ if (i < 0) { i += len; }
+ for (;i<len;i++) {
+ if (i in this && this[i] === item) { return i; }
+ }
+ return -1;
+ }
+}
+if (!Array.indexOf) {
+ Array.indexOf = function(obj, item, from) { return Array.prototype.indexOf.call(obj, item, from); }
+}
+
+if (!Array.prototype.lastIndexOf) {
+ Array.prototype.lastIndexOf = function(item, from) {
+ var len = this.length;
+ var i = from || len-1;
+ if (i < 0) { i += len; }
+ for (;i>-1;i--) {
+ if (i in this && this[i] === item) { return i; }
+ }
+ return -1;
+ }
+}
+if (!Array.lastIndexOf) {
+ Array.lastIndexOf = function(obj, item, from) { return Array.prototype.lastIndexOf.call(obj, item, from); }
+}
+
+if (!Array.prototype.forEach) {
+ Array.prototype.forEach = function(cb, _this) {
+ var len = this.length;
+ for (var i=0;i<len;i++) {
+ if (i in this) { cb.call(_this, this[i], i, this); }
+ }
+ }
+}
+if (!Array.forEach) {
+ Array.forEach = function(obj, cb, _this) { Array.prototype.forEach.call(obj, cb, _this); }
+}
+
+if (!Array.prototype.every) {
+ Array.prototype.every = function(cb, _this) {
+ var len = this.length;
+ for (var i=0;i<len;i++) {
+ if (i in this && !cb.call(_this, this[i], i, this)) { return false; }
+ }
+ return true;
+ }
+}
+if (!Array.every) {
+ Array.every = function(obj, cb, _this) { return Array.prototype.every.call(obj, cb, _this); }
+}
+
+if (!Array.prototype.some) {
+ Array.prototype.some = function(cb, _this) {
+ var len = this.length;
+ for (var i=0;i<len;i++) {
+ if (i in this && cb.call(_this, this[i], i, this)) { return true; }
+ }
+ return false;
+ }
+}
+if (!Array.some) {
+ Array.some = function(obj, cb, _this) { return Array.prototype.some.call(obj, cb, _this); }
+}
+
+if (!Array.prototype.map) {
+ Array.prototype.map = function(cb, _this) {
+ var len = this.length;
+ var res = new Array(len);
+ for (var i=0;i<len;i++) {
+ if (i in this) { res[i] = cb.call(_this, this[i], i, this); }
+ }
+ return res;
+ }
+}
+if (!Array.map) {
+ Array.map = function(obj, cb, _this) { return Array.prototype.map.call(obj, cb, _this); }
+}
+
+if (!Array.prototype.filter) {
+ Array.prototype.filter = function(cb, _this) {
+ var len = this.length;
+ var res = [];
+ for (var i=0;i<len;i++) {
+ if (i in this) {
+ var val = this[i];
+ if (cb.call(_this, val, i, this)) { res.push(val); }
+ }
+ }
+ return res;
+ }
+}
+if (!Array.filter) {
+ Array.filter = function(obj, cb, _this) { return Array.prototype.filter.call(obj, cb, _this); }
+}
diff --git a/js/wwwsqldesigner.js b/js/wwwsqldesigner.js
new file mode 100644
index 0000000..89e80cf
--- /dev/null
+++ b/js/wwwsqldesigner.js
@@ -0,0 +1,2185 @@
+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 = null;
+ this.data.def = null;
+ this.data.nll = false;
+ 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 = "&raquo;&nbsp;";
+
+ 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<this.relations.length;i++) {
+ var r = this.relations[i];
+ if (r.row1 != this) { continue; }
+ var tt = r.row2.getTitle().replace(new RegExp(old,"g"),t);
+ if (tt != r.row2.getTitle()) { r.row2.setTitle(tt); }
+ }
+ SQL.Visual.prototype.setTitle.apply(this, [t]);
+}
+
+SQL.Row.prototype.click = function(e) { /* clicked on row */
+ OZ.Event.stop(e);
+ this.owner.owner.rowManager.select(this);
+}
+
+SQL.Row.prototype.dblclick = function(e) { /* clicked on row */
+ OZ.Event.prevent(e);
+ OZ.Event.stop(e);
+ this.expand();
+}
+
+SQL.Row.prototype.mousedown = function(e) {
+ OZ.Event.stop(e);
+ this.owner.owner.tableManager.select(this.owner);
+}
+
+SQL.Row.prototype.update = function(data) { /* update subset of row data */
+ for (var p in data) { this.data[p] = data[p]; }
+ var elm = this.getDataType();
+ for (var i=0;i<this.relations.length;i++) {
+ var r = this.relations[i];
+ if (r.row1 == this) { r.row2.update({type:this.data.type,size:this.data.size}); }
+ }
+ this.redraw();
+}
+
+SQL.Row.prototype.up = function() { /* shift up */
+ var r = this.owner.rows;
+ var idx = r.indexOf(this);
+ if (!idx) { return; }
+ r[idx-1].dom.container.parentNode.insertBefore(this.dom.container,r[idx-1].dom.container);
+ r.splice(idx,1);
+ r.splice(idx-1,0,this);
+ this.redraw();
+}
+
+SQL.Row.prototype.down = function() { /* shift down */
+ var r = this.owner.rows;
+ var idx = r.indexOf(this);
+ if (idx+1 == this.owner.rows.length) { return; }
+ r[idx].dom.container.parentNode.insertBefore(this.dom.container,r[idx+1].dom.container.nextSibling);
+ r.splice(idx,1);
+ r.splice(idx+1,0,this);
+ this.redraw();
+}
+
+SQL.Row.prototype.buildContent = function() {
+ var elms = [];
+ this.dom.name = OZ.DOM.elm("input");
+ this.dom.name.type = "text";
+ elms.push(["name",this.dom.name]);
+ OZ.Event.add(this.dom.name, "keypress", this.enter);
+
+ this.dom.type = this.buildTypeSelect(this.data.type);
+ elms.push(["type",this.dom.type]);
+
+ this.dom.size = OZ.DOM.elm("input");
+ this.dom.size.type = "text";
+ elms.push(["size",this.dom.size]);
+
+ this.dom.def = OZ.DOM.elm("input");
+ this.dom.def.type = "text";
+ elms.push(["def",this.dom.def]);
+
+ this.dom.ai = OZ.DOM.elm("input");
+ this.dom.ai.type = "checkbox";
+ elms.push(["ai",this.dom.ai]);
+
+ this.dom.nll = OZ.DOM.elm("input");
+ this.dom.nll.type = "checkbox";
+ elms.push(["notnull",this.dom.nll]);
+
+ this.dom.commentbtn = OZ.DOM.elm("input");
+ this.dom.commentbtn.type = "button";
+ this.dom.commentbtn.value = _("comment");
+
+ OZ.Event.add(this.dom.commentbtn, "click", this.changeComment);
+
+ for (var i=0;i<elms.length;i++) {
+ var row = elms[i];
+ var l = OZ.DOM.text(_(row[0])+": ");
+ this.dom.content.appendChild(l);
+ this.dom.content.appendChild(row[1]);
+ this.dom.content.appendChild(OZ.DOM.elm("br"));
+ }
+
+ this.dom.comment = OZ.DOM.elm("span",{className:"comment"});
+ this.dom.comment.innerHTML = this.data.comment;
+
+ this.dom.content.appendChild(this.dom.comment);
+ this.dom.content.appendChild(this.dom.commentbtn);
+}
+
+SQL.Row.prototype.changeComment = function(e) {
+ var c = prompt(_("commenttext"),this.data.comment);
+ this.data.comment = c || "";
+ this.dom.comment.innerHTML = this.data.comment;
+}
+
+SQL.Row.prototype.expand = function() {
+ if (this.expanded) { return; }
+ this.expanded = true;
+ this.dom.title.style.display = "none";
+ this.dom.content.style.display = "block";
+ this.buildContent();
+ this.load();
+ this.redraw();
+ this.dom.name.focus();
+ this.dom.name.select();
+}
+
+SQL.Row.prototype.collapse = function() {
+ if (!this.expanded) { return; }
+ this.expanded = false;
+
+ this.setTitle(this.dom.name.value);
+ var data = {
+ type: this.dom.type.selectedIndex,
+ def: this.dom.def.value,
+ size: this.dom.size.value,
+ nll: !this.dom.nll.checked,
+ ai: this.dom.ai.checked
+ }
+
+ OZ.DOM.clear(this.dom.content);
+ this.dom.content.style.display = "none";
+ this.dom.title.style.display = "block";
+ this.update(data);
+ /* gecko hack */
+ this.owner.moveBy(1,1);
+ this.owner.moveBy(-1,-1);
+}
+
+SQL.Row.prototype.load = function() { /* put data to expanded form */
+ this.dom.name.value = this.getTitle();
+ this.dom.def.value = this.data.def;
+ this.dom.size.value = this.data.size || null;
+ this.dom.nll.checked = !this.data.nll;
+ this.dom.ai.checked = this.data.ai;
+}
+
+SQL.Row.prototype.redraw = function() {
+ var color = this.getColor();
+ this.dom.container.style.backgroundColor = color;
+ OZ.DOM.removeClass(this.dom.container,"primary");
+ if (this.isPrimary()) { OZ.DOM.addClass(this.dom.container,"primary"); }
+ this.dom.selected.style.display = (this.selected ? "" : "none");
+ this.owner.redraw();
+ this.owner.owner.rowManager.redraw();
+}
+
+SQL.Row.prototype.addRelation = function(r) {
+ this.relations.push(r);
+}
+
+SQL.Row.prototype.removeRelation = function(r) {
+ var idx = this.relations.indexOf(r);
+ if (idx == -1) { return; }
+ this.relations.splice(idx,1);
+}
+
+SQL.Row.prototype.addKey = function(k) {
+ this.keys.push(k);
+ this.redraw();
+}
+
+SQL.Row.prototype.removeKey = function(k) {
+ var idx = this.keys.indexOf(k);
+ if (idx == -1) { return; }
+ this.keys.splice(idx,1);
+ this.redraw();
+}
+
+SQL.Row.prototype.getDataType = function() {
+ var type = this.data.type;
+ var elm = DATATYPES.getElementsByTagName("type")[type];
+ return elm;
+}
+
+SQL.Row.prototype.getColor = function() {
+ var elm = this.getDataType();
+ var g = this.getDataType().parentNode;
+ return elm.getAttribute("color") || g.getAttribute("color") || "#fff";
+}
+
+SQL.Row.prototype.buildTypeSelect = function(id) { /* build selectbox with avail datatypes */
+ var s = OZ.DOM.elm("select");
+ var gs = DATATYPES.getElementsByTagName("group");
+ for (var i=0;i<gs.length;i++) {
+ var g = gs[i];
+ var og = OZ.DOM.elm("optgroup");
+ og.style.backgroundColor = g.getAttribute("color") || "#fff";
+ og.label = g.getAttribute("label");
+ s.appendChild(og);
+ var ts = g.getElementsByTagName("type");
+ for (var j=0;j<ts.length;j++) {
+ var t = ts[j];
+ var o = OZ.DOM.elm("option");
+ if (t.getAttribute("color")) { o.style.backgroundColor = t.getAttribute("color"); }
+ if (t.getAttribute("note")) { o.title = t.getAttribute("note"); }
+ o.innerHTML = t.getAttribute("label");
+ og.appendChild(o);
+ }
+ }
+ s.selectedIndex = id;
+ return s;
+}
+
+SQL.Row.prototype.destroy = function() {
+ SQL.Visual.prototype.destroy.apply(this);
+ while (this.relations.length) {
+ this.owner.owner.removeRelation(this.relations[0]);
+ }
+ for (var i=0;i<this.keys.length;i++){
+ this.keys[i].removeRow(this);
+ }
+}
+
+SQL.Row.prototype.toXML = function() {
+ var xml = "";
+
+ var t = this.getTitle().replace(/"/g,"&quot;");
+ var nn = (this.data.nll ? "1" : "0");
+ var ai = (this.data.ai ? "1" : "0");
+ xml += '<row name="'+t+'" null="'+nn+'" autoincrement="'+ai+'">';
+
+ var elm = this.getDataType();
+ var t = elm.getAttribute("sql");
+ if (elm.getAttribute("length") == "1" && this.data.size) { t += "("+this.data.size+")"; }
+ xml += "<datatype>"+t+"</datatype>";
+
+ if (this.data.def) {
+ var q = elm.getAttribute("quote");
+ var d = this.data.def || "";
+ if (d != "NULL" && d != "null" && d != "CURRENT_TIMESTAMP") { d = q+d+q; }
+ xml += "<default>"+d+"</default>";
+ }
+
+ for (var i=0;i<this.relations.length;i++) {
+ var r = this.relations[i];
+ if (r.row2 != this) { continue; }
+ xml += '<relation table="'+r.row1.owner.getTitle()+'" row="'+r.row1.getTitle()+'" />';
+ }
+
+ if (this.data.comment) {
+ var escaped = this.data.comment.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;");
+ xml += "<comment>"+escaped+"</comment>";
+ }
+
+ xml += "</row>";
+ return xml;
+}
+
+SQL.Row.prototype.fromXML = function(node) {
+ var name = node.getAttribute("name");
+ this.setTitle(name);
+
+ var obj = { type:0, size:null };
+ 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<types.length;i++) {
+ var sql = types[i].getAttribute("sql");
+ var re = types[i].getAttribute("re");
+ if (sql == type || (re && new RegExp(re).exec(type)) ) { obj.type = i; }
+ }
+ }
+
+ var elm = DATATYPES.getElementsByTagName("type")[obj.type];
+ var d = node.getElementsByTagName("default");
+ if (d.length && d[0].firstChild) {
+ var def = d[0].firstChild.nodeValue;
+ obj.def = def;
+ var q = elm.getAttribute("quote");
+ if (q) {
+ var re = new RegExp("^"+q+"(.*)"+q+"$");
+ var r = def.match(re);
+ if (r) { obj.def = r[1]; }
+ }
+ }
+
+ this.update(obj);
+}
+
+SQL.Row.prototype.isPrimary = function() {
+ for (var i=0;i<this.keys.length;i++) {
+ var k = this.keys[i];
+ if (k.getType() == "PRIMARY") { return true; }
+ }
+ return false;
+}
+
+SQL.Row.prototype.enter = function(e) {
+ if (e.keyCode == 13) {
+ this.collapse();
+ }
+}
+
+/* --------------------------- relation (connector) ----------- */
+
+SQL.Relation = OZ.Class().extend(SQL.Visual);
+
+SQL.Relation.prototype.init = function(owner, row1, row2) {
+ 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 (this.owner.vector == "svg") {
+ var path = document.createElementNS(this.owner.svgNS, "path");
+ path.setAttribute("stroke","black");
+ 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 = "#000";
+ 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<this.dom.length;i++) {
+ this.dom[i].style.visibility = "";
+ }
+}
+
+SQL.Relation.prototype.hide = function() {
+ this.hidden = true;
+ for (var i=0;i<this.dom.length;i++) {
+ this.dom[i].style.visibility = "hidden";
+ }
+}
+
+SQL.Relation.prototype.redrawNormal = function(p1, p2, half) {
+ if (this.owner.vector == "svg") {
+ var str = "M "+p1[0]+" "+p1[1]+" C "+(p1[0] + half)+" "+p1[1]+" ";
+ str += (p2[0]-half)+" "+p2[1]+" "+p2[0]+" "+p2[1];
+ this.dom[0].setAttribute("d",str);
+ } else if (this.owner.vector == "vml") {
+ this.dom[0].from = p1[0]+" "+p1[1];
+ this.dom[0].to = p2[0]+" "+p2[1];
+ this.dom[0].control1 = (p1[0]+half)+" "+p1[1];
+ this.dom[0].control2 = (p2[0]-half)+" "+p2[1];
+ } else {
+ this.dom[0].style.left = p1[0]+"px";
+ this.dom[0].style.top = p1[1]+"px";
+ this.dom[0].style.width = half+"px";
+
+ this.dom[1].style.left = (p1[0] + half) + "px";
+ this.dom[1].style.top = Math.min(p1[1],p2[1]) + "px";
+ this.dom[1].style.height = (Math.abs(p1[1] - p2[1])+CONFIG.RELATION_THICKNESS)+"px";
+
+ this.dom[2].style.left = (p1[0]+half+1)+"px";
+ this.dom[2].style.top = p2[1]+"px";
+ this.dom[2].style.width = half+"px";
+ }
+}
+
+SQL.Relation.prototype.redrawSide = function(p1, p2, x) {
+ if (this.owner.vector == "svg") {
+ var str = "M "+p1[0]+" "+p1[1]+" C "+x+" "+p1[1]+" ";
+ str += x+" "+p2[1]+" "+p2[0]+" "+p2[1];
+ this.dom[0].setAttribute("d",str);
+ } else if (this.owner.vector == "vml") {
+ this.dom[0].from = p1[0]+" "+p1[1];
+ this.dom[0].to = p2[0]+" "+p2[1];
+ this.dom[0].control1 = x+" "+p1[1];
+ this.dom[0].control2 = x+" "+p2[1];
+ } else {
+ this.dom[0].style.left = Math.min(x,p1[0])+"px";
+ this.dom[0].style.top = p1[1]+"px";
+ this.dom[0].style.width = Math.abs(p1[0]-x)+"px";
+
+ this.dom[1].style.left = x+"px";
+ this.dom[1].style.top = Math.min(p1[1],p2[1]) + "px";
+ this.dom[1].style.height = (Math.abs(p1[1] - p2[1])+CONFIG.RELATION_THICKNESS)+"px";
+
+ this.dom[2].style.left = Math.min(x,p2[0])+"px";
+ this.dom[2].style.top = p2[1]+"px";
+ this.dom[2].style.width = Math.abs(p2[0]-x)+"px";
+ }
+}
+
+SQL.Relation.prototype.redraw = function() { /* draw connector */
+ if (this.hidden) { return; }
+ var t1 = this.row1.owner.dom.container;
+ var t2 = this.row2.owner.dom.container;
+
+ var l1 = t1.offsetLeft;
+ var l2 = t2.offsetLeft;
+ var r1 = l1 + t1.offsetWidth;
+ var r2 = l2 + t2.offsetWidth;
+ var t1 = t1.offsetTop + this.row1.dom.container.offsetTop + Math.round(this.row1.dom.container.offsetHeight/2);
+ var t2 = t2.offsetTop + this.row2.dom.container.offsetTop + Math.round(this.row2.dom.container.offsetHeight/2);
+
+ if (this.row1.owner.selected) { t1++; l1++; r1--; }
+ if (this.row2.owner.selected) { t2++; l2++; r2--; }
+
+ var p1 = [0,0];
+ var p2 = [0,0];
+
+ if (r1 < l2 || r2 < l1) { /* between tables */
+ if (Math.abs(r1 - l2) < Math.abs(r2 - l1)) {
+ p1 = [r1,t1];
+ p2 = [l2,t2];
+ } else {
+ p1 = [r2,t2];
+ p2 = [l1,t1];
+ }
+ var half = Math.floor((p2[0] - p1[0])/2);
+ this.redrawNormal(p1, p2, half);
+ } else { /* next to tables */
+ var x = 0;
+ var l = 0;
+ if (Math.abs(l1 - l2) < Math.abs(r1 - r2)) { /* left of tables */
+ p1 = [l1,t1];
+ p2 = [l2,t2];
+ x = Math.min(l1,l2) - CONFIG.RELATION_SPACING;
+ } else { /* right of tables */
+ p1 = [r1,t1];
+ p2 = [r2,t2];
+ x = Math.max(r1,r2) + CONFIG.RELATION_SPACING;
+ }
+ this.redrawSide(p1, p2, x);
+ } /* line next to tables */
+}
+
+SQL.Relation.prototype.destroy = function() {
+ this.row1.removeRelation(this);
+ this.row2.removeRelation(this);
+ for (var i=0;i<this.dom.length;i++) {
+ this.dom[i].parentNode.removeChild(this.dom[i]);
+ }
+}
+
+/* --------------------- db table ------------ */
+
+SQL.Table = OZ.Class().extend(SQL.Visual);
+
+SQL.Table.prototype.init = function(owner, name, x, y, z) {
+ this.owner = owner;
+ this.rows = [];
+ this.keys = [];
+ this.zIndex = 0;
+
+ this.flag = false;
+ this.selected = false;
+ SQL.Visual.prototype.init.apply(this);
+ this.data.comment = "";
+
+ this.dom.container.className = "table";
+ this.setTitle(name);
+ this.x = x || 0;
+ this.y = y || 0;
+ this.setZ(z);
+}
+
+SQL.Table.prototype._build = function() {
+ this.dom.mini = OZ.DOM.elm("div",{className:"mini"});
+
+ this.dom.title.className = "table_title";
+
+ OZ.DOM.append([this.dom.container,this.dom.title,this.dom.content]);
+ this.owner.map.dom.content.appendChild(this.dom.mini);
+
+ 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.down));
+
+ /* shadows */
+ var cn = ["shadow-corner","shadow-right","shadow-bottom"];
+ for (var i=0;i<cn.length;i++) {
+ var d = OZ.DOM.elm("div",{className:cn[i]});
+ this.dom.container.appendChild(d);
+ }
+}
+
+SQL.Table.prototype.setTitle = function(t) {
+ var old = this.getTitle();
+ for (var i=0;i<this.rows.length;i++) {
+ var row = this.rows[i];
+ for (var j=0;j<row.relations.length;j++) {
+ var r = row.relations[j];
+ if (r.row1 != row) { continue; }
+ var tt = row.getTitle().replace(new RegExp(old,"g"),t);
+ if (tt != row.getTitle()) { row.setTitle(tt); }
+ }
+ }
+ SQL.Visual.prototype.setTitle.apply(this, [t]);
+}
+
+SQL.Table.prototype.getRelations = function() {
+ var arr = [];
+ for (var i=0;i<this.rows.length;i++) {
+ var row = this.rows[i];
+ for (var j=0;j<row.relations.length;j++) {
+ var r = row.relations[j];
+ if (arr.indexOf(r) == -1) { arr.push(r); }
+ }
+ }
+ return arr;
+}
+
+SQL.Table.prototype.showRelations = function() {
+ var rs = this.getRelations();
+ for (var i=0;i<rs.length;i++) { rs[i].show(); }
+}
+
+SQL.Table.prototype.hideRelations = function() {
+ var rs = this.getRelations();
+ for (var i=0;i<rs.length;i++) { rs[i].hide(); }
+}
+
+SQL.Table.prototype.click = function(e) {
+ OZ.Event.stop(e);
+ this.dispatch("tableclick",this);
+ this.owner.rowManager.select(false);
+}
+
+SQL.Table.prototype.dblclick = function() {
+ this.owner.tableManager.edit();
+}
+
+SQL.Table.prototype.select = function() {
+ if (this.selected) { return; }
+ this.selected = true;
+ OZ.DOM.addClass(this.dom.container,"table_selected");
+ OZ.DOM.addClass(this.dom.mini,"mini_selected");
+ this.redraw();
+}
+
+SQL.Table.prototype.deselect = function() {
+ if (!this.selected) { return; }
+ this.selected = false;
+ OZ.DOM.removeClass(this.dom.container,"table_selected");
+ OZ.DOM.removeClass(this.dom.mini,"mini_selected");
+ this.redraw();
+}
+
+SQL.Table.prototype.addRow = function(title, data) {
+ var r = new SQL.Row(this, title, data);
+ this.rows.push(r);
+ this.dom.content.appendChild(r.dom.container);
+ this.redraw();
+ return r;
+}
+
+SQL.Table.prototype.removeRow = function(r) {
+ var idx = this.rows.indexOf(r);
+ if (idx == -1) { return; }
+ r.destroy();
+ this.rows.splice(idx,1);
+ this.redraw();
+}
+
+SQL.Table.prototype.addKey = function(name) {
+ var k = new SQL.Key(this, name);
+ this.keys.push(k);
+ return k;
+}
+
+SQL.Table.prototype.removeKey = function(i) {
+ var idx = this.keys.indexOf(k);
+ if (idx == -1) { return; }
+ k.destroy();
+ this.keys.splice(idx,1);
+}
+
+SQL.Table.prototype.redraw = function() {
+ var x = this.x;
+ var y = this.y;
+ if (this.selected) { x--; y--; }
+ this.dom.container.style.left = x+"px";
+ this.dom.container.style.top = y+"px";
+
+ var ratioX = this.owner.map.width / this.owner.width;
+ var ratioY = this.owner.map.height / this.owner.height;
+
+ var w = this.dom.container.offsetWidth * ratioX;
+ var h = this.dom.container.offsetHeight * ratioY;
+ var x = this.x * ratioX;
+ var y = this.y * ratioY;
+
+ this.dom.mini.style.width = Math.round(w)+"px";
+ this.dom.mini.style.height = Math.round(h)+"px";
+ this.dom.mini.style.left = Math.round(x)+"px";
+ this.dom.mini.style.top = Math.round(y)+"px";
+
+ var rs = this.getRelations();
+ for (var i=0;i<rs.length;i++) { rs[i].redraw(); }
+}
+
+SQL.Table.prototype.moveBy = function(dx, dy, snap) {
+ this.x += dx;
+ this.y += dy;
+
+ if (snap) {
+ this.x = Math.round(this.x / snap) * snap;
+ this.y = Math.round(this.y / snap) * snap;
+ }
+
+ this.redraw();
+}
+
+SQL.Table.prototype.moveTo = function(x, y) {
+ this.x = x;
+ this.y = y;
+ this.redraw();
+}
+
+SQL.Table.prototype.down = function(e) { /* mousedown - start drag */
+ OZ.Event.prevent(e);
+ this.owner.tableManager.select(this);
+
+ SQL.Table.active = this;
+ SQL.Table.x = e.clientX;
+ SQL.Table.y = e.clientY;
+
+ if (this.owner.getOption("hide")) { this.hideRelations(); }
+}
+
+SQL.Table.prototype.toXML = function() {
+ var t = this.getTitle().replace(/"/g,"&quot;");
+ var xml = "";
+ xml += '<table x="'+this.x+'" y="'+this.y+'" name="'+t+'">';
+ for (var i=0;i<this.rows.length;i++) {
+ xml += this.rows[i].toXML();
+ }
+ for (var i=0;i<this.keys.length;i++) {
+ xml += this.keys[i].toXML();
+ }
+ var c = this.getComment();
+ if (c) {
+ c = c.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;");
+ xml += "<comment>"+c+"</comment>";
+ }
+ xml += "</table>";
+ 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<rows.length;i++) {
+ var row = rows[i];
+ var r = this.addRow("");
+ r.fromXML(row);
+ }
+ var keys = node.getElementsByTagName("key");
+ for (var i=0;i<keys.length;i++) {
+ var key = keys[i];
+ var k = this.addKey();
+ k.fromXML(key);
+ }
+ for (var i=0;i<node.childNodes.length;i++) {
+ var ch = node.childNodes[i];
+ if (ch.tagName && ch.tagName.toLowerCase() == "comment" && ch.firstChild) {
+ this.setComment(ch.firstChild.nodeValue);
+ }
+ }
+}
+
+SQL.Table.prototype.getZ = function() {
+ return this.zIndex;
+}
+
+SQL.Table.prototype.setZ = function(z) {
+ this.zIndex = z;
+ this.dom.container.style.zIndex = z;
+}
+
+SQL.Table.prototype.findNamedRow = function(n) { /* return row with a given name */
+ for (var i=0;i<this.rows.length;i++) {
+ if (this.rows[i].getTitle() == n) { return this.rows[i]; }
+ }
+ return false;
+}
+
+SQL.Table.prototype.addKey = function(type, name) {
+ var i = new SQL.Key(this, type, name);
+ this.keys.push(i);
+ return i;
+}
+
+SQL.Table.prototype.removeKey = function(i) {
+ var idx = this.keys.indexOf(i);
+ if (idx == -1) { return; }
+ i.destroy();
+ this.keys.splice(idx,1);
+}
+
+SQL.Table.prototype.setComment = function(c) {
+ this.data.comment = c;
+}
+
+SQL.Table.prototype.getComment = function() {
+ return this.data.comment;
+}
+
+SQL.Table.move = function(e) { /* mousemove */
+ var t = SQL.Table;
+ if (!t.active) { return; }
+ SQL.Designer.removeSelection();
+ var dx = e.clientX - t.x;
+ var dy = e.clientY - t.y;
+ t.active.moveBy(dx, dy);
+ t.x = e.clientX;
+ t.y = e.clientY;
+}
+
+SQL.Table.up = function(e) {
+ var t = SQL.Table;
+ var d = SQL.Designer;
+ if (!t.active) { return; }
+ if (d.getOption("hide")) { t.active.showRelations(); }
+ t.active.moveBy(0,0, parseInt(d.getOption("snap")));
+ t.active = false;
+}
+
+OZ.Event.add(document, "mousemove", SQL.Table.move);
+OZ.Event.add(document, "mouseup", SQL.Table.up);
+
+SQL.Table.prototype.destroy = function() {
+ SQL.Visual.prototype.destroy.apply(this);
+ this.dom.mini.parentNode.removeChild(this.dom.mini);
+ while (this.rows.length) {
+ this.removeRow(this.rows[0]);
+ }
+}
+
+/* --------------------- db index ------------ */
+
+SQL.Key = OZ.Class().extend(SQL.Visual);
+
+SQL.Key.prototype.init = function(owner, type, name) {
+ this.owner = owner;
+ this.rows = [];
+ this.type = type || "INDEX";
+ this.name = name || "";
+ SQL.Visual.prototype.init.apply(this);
+}
+
+SQL.Key.prototype.setName = function(n) {
+ this.name = n;
+}
+
+SQL.Key.prototype.getName = function() {
+ return this.name;
+}
+
+SQL.Key.prototype.setType = function(t) {
+ if (!t) { return; }
+ this.type = t;
+ for (var i=0;i<this.rows.length;i++) { this.rows[i].redraw(); }
+}
+
+SQL.Key.prototype.getType = function() {
+ return this.type;
+}
+
+SQL.Key.prototype.addRow = function(r) {
+ if (r.owner != this.owner) { return; }
+ this.rows.push(r);
+ r.addKey(this);
+}
+
+SQL.Key.prototype.removeRow = function(r) {
+ var idx = this.rows.indexOf(r);
+ if (idx == -1) { return; }
+ r.removeKey(this);
+ this.rows.splice(idx,1);
+}
+
+SQL.Key.prototype.destroy = function() {
+ for (var i=0;i<this.rows.length;i++) {
+ this.rows[i].removeKey(this);
+ }
+}
+
+SQL.Key.prototype.getLabel = function() {
+ return this.name || this.type;
+}
+
+SQL.Key.prototype.toXML = function() {
+ var xml = "";
+ xml += '<key type="'+this.getType()+'" name="'+this.getName()+'">';
+ for (var i=0;i<this.rows.length;i++) {
+ var r = this.rows[i];
+ xml += '<part>'+r.getTitle()+'</part>';
+ }
+ xml += '</key>';
+ 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<parts.length;i++) {
+ var name = parts[i].firstChild.nodeValue;
+ var row = this.owner.findNamedRow(name);
+ this.addRow(row);
+ }
+}
+
+/* --------------------- minimap ------------ */
+
+SQL.Map = OZ.Class().extend(SQL.Visual);
+
+SQL.Map.prototype.init = function(owner) {
+ this.owner = owner;
+ SQL.Visual.prototype.init.apply(this);
+ this.dom.container = this.dom.content = OZ.$("minimap");
+ this.width = this.dom.container.offsetWidth - 2;
+ this.height = this.dom.container.offsetHeight - 2;
+
+ this.dom.port = OZ.DOM.elm("div",{className:"port",zIndex:10});
+ this.dom.container.appendChild(this.dom.port);
+ this.sync = this.bind(this.sync);
+
+ this.flag = false;
+ this.sync();
+
+ OZ.Event.add(window, "resize", this.sync);
+ OZ.Event.add(window, "scroll", this.sync);
+ OZ.Event.add(this.dom.container, "mousedown", this.bind(this.down));
+ OZ.Event.add(document, "mousemove", this.bind(this.move));
+ OZ.Event.add(document, "mouseup", this.bind(this.up));
+}
+
+SQL.Map.prototype.down = function(e) { /* mousedown - move view and start drag */
+ this.flag = true;
+ this.dom.container.style.cursor = "move";
+ var pos = OZ.DOM.pos(this.dom.container);
+
+ this.x = Math.round(pos[0] + this.l + this.w/2);
+ this.y = Math.round(pos[1] + this.t + this.h/2);
+ this.move(e);
+}
+
+SQL.Map.prototype.move = function(e) { /* mousemove */
+ if (!this.flag) { return; }
+ OZ.Event.prevent(e);
+
+ var dx = e.clientX - this.x;
+ var dy = e.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;
+ 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 = "";
+}
+
+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.dom = {
+ container:OZ.$("io")
+ };
+
+ var ids = ["saveload","clientsave","clientload","clientsql","serversave","serverload","serverlist","serverimport"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ this.dom[id] = elm;
+ elm.value = _(id);
+ }
+
+ var ids = ["client","server","output","backendlabel"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ elm.innerHTML = _(id);
+ }
+
+ this.dom.ta = OZ.$("textarea");
+ this.dom.backend = OZ.$("backend");
+
+ this.dom.container.parentNode.removeChild(this.dom.container);
+ this.dom.container.style.visibility = "";
+
+ this.saveresponse = this.bind(this.saveresponse);
+ this.loadresponse = this.bind(this.loadresponse);
+ this.listresponse = this.bind(this.listresponse);
+ this.importresponse = this.bind(this.importresponse);
+
+ OZ.Event.add(this.dom.saveload, "click", this.bind(this.click));
+ OZ.Event.add(this.dom.clientsave, "click", this.bind(this.clientsave));
+ OZ.Event.add(this.dom.clientload, "click", this.bind(this.clientload));
+ OZ.Event.add(this.dom.clientsql, "click", this.bind(this.clientsql));
+ OZ.Event.add(this.dom.serversave, "click", this.bind(this.serversave));
+ OZ.Event.add(this.dom.serverload, "click", this.bind(this.serverload));
+ OZ.Event.add(this.dom.serverlist, "click", this.bind(this.serverlist));
+ OZ.Event.add(this.dom.serverimport, "click", this.bind(this.serverimport));
+ this.build();
+}
+
+SQL.IO.prototype.build = function() {
+ OZ.DOM.clear(this.dom.backend);
+
+ var bs = CONFIG.AVAILABLE_BACKENDS;
+ var def = CONFIG.DEFAULT_BACKEND;
+ for (var i=0;i<bs.length;i++) {
+ var o = OZ.DOM.elm("option");
+ o.value = bs[i];
+ o.innerHTML = bs[i];
+ this.dom.backend.appendChild(o);
+ if (bs[i] == def) { this.dom.backend.selectedIndex = i; }
+ }
+}
+
+SQL.IO.prototype.click = function() { /* open io dialog */
+ this.build();
+ this.dom.ta.value = "";
+ this.dom.clientsql.value = _("clientsql") + " (" + window.DATATYPES.getAttribute("db") + ")";
+ this.owner.window.open(_("saveload"),this.dom.container);
+}
+
+SQL.IO.prototype.fromXML = function(xmlDoc) {
+ if (!xmlDoc || !xmlDoc.documentElement) {
+ alert(_("xmlerror")+': Null document');
+ return false;
+ }
+ this.owner.fromXML(xmlDoc.documentElement);
+ this.owner.window.close();
+ return true;
+}
+
+SQL.IO.prototype.clientsave = function() {
+ var xml = this.owner.toXML();
+ this.dom.ta.value = xml;
+}
+
+SQL.IO.prototype.clientload = function() {
+ var xml = this.dom.ta.value;
+ if (!xml) {
+ alert(_("empty"));
+ return;
+ }
+ try {
+ if (window.DOMParser) {
+ var parser = new DOMParser();
+ var xmlDoc = parser.parseFromString(xml, "text/xml");
+ } else if (window.ActiveXObject) {
+ var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.loadXML(xml);
+ } else {
+ throw new Error("No XML parser available.");
+ }
+ } catch(e) {
+ alert(_("xmlerror")+': '+e.message);
+ return;
+ }
+ this.fromXML(xmlDoc);
+}
+
+SQL.IO.prototype.clientsql = function() {
+ var path = "db/"+window.DATATYPES.getAttribute("db")+"/output.xsl";
+ this.owner.window.showThrobber();
+ OZ.Request(path, this.bind(this.finish), {xml:true});
+}
+
+SQL.IO.prototype.finish = function(xslDoc) {
+ this.owner.window.hideThrobber();
+ var xml = this.owner.toXML();
+ var sql = "";
+ try {
+ if (window.XSLTProcessor && window.DOMParser) {
+ var parser = new DOMParser();
+ var xmlDoc = parser.parseFromString(xml, "text/xml");
+ var xsl = new XSLTProcessor();
+ xsl.importStylesheet(xslDoc);
+ var result = xsl.transformToDocument(xmlDoc);
+ sql = result.documentElement.textContent;
+ } else if (window.ActiveXObject) {
+ var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.loadXML(xml);
+ sql = xmlDoc.transformNode(xslDoc);
+ } else {
+ throw new Error("No XSLT processor available");
+ }
+ } catch(e) {
+ alert(_("xmlerror")+': '+e.message);
+ return;
+ }
+ this.dom.ta.value = sql;
+}
+
+SQL.IO.prototype.serversave = function(e) {
+ var name = prompt(_("serversaveprompt"),"");
+ if (!name) { return; }
+ var xml = this.owner.toXML();
+ var url = "backend/"+this.dom.backend.value+"/?action=save&keyword="+encodeURIComponent(name);
+ var h = {"Content-type":"application/xml"};
+ this.owner.window.showThrobber();
+ this.owner.setTitle(name);
+ OZ.Request(url, this.saveresponse, {xml:true, method:"post", data:xml, headers:h});
+}
+
+SQL.IO.prototype.serverload = function(e, keyword) {
+ var name = keyword || prompt(_("serverloadprompt"),"");
+ if (!name) { return; }
+ var url = "backend/"+this.dom.backend.value+"/?action=load&keyword="+encodeURIComponent(name);
+ this.owner.window.showThrobber();
+ this.name = name;
+ OZ.Request(url, this.loadresponse, {xml:true});
+}
+
+SQL.IO.prototype.serverlist = function(e) {
+ var url = "backend/"+this.dom.backend.value+"/?action=list";
+ this.owner.window.showThrobber();
+ OZ.Request(url, this.listresponse);
+}
+
+SQL.IO.prototype.serverimport = function(e) {
+ var name = prompt(_("serverimportprompt"),"");
+ if (!name) { return; }
+ var url = "backend/"+this.dom.backend.value+"/?action=import&database="+name;
+ this.owner.window.showThrobber();
+ OZ.Request(url, this.importresponse, {xml:true});
+}
+
+SQL.IO.prototype.check = function(code) {
+ switch (code) {
+ case 201:
+ case 404:
+ case 500:
+ case 501:
+ case 503:
+ var lang = "http"+code;
+ this.dom.ta.value = _("httpresponse")+": "+_(lang);
+ return false;
+ break;
+ default: return true;
+ }
+}
+
+SQL.IO.prototype.saveresponse = function(data, code) {
+ this.owner.window.hideThrobber();
+ this.check(code);
+}
+
+SQL.IO.prototype.loadresponse = function(data, code) {
+ this.owner.window.hideThrobber();
+ if (!this.check(code)) { return; }
+ this.fromXML(data);
+ this.owner.setTitle(this.name);
+}
+
+SQL.IO.prototype.listresponse = function(data, code) {
+ this.owner.window.hideThrobber();
+ if (!this.check(code)) { return; }
+ this.dom.ta.value = data;
+}
+
+SQL.IO.prototype.importresponse = function(data, code) {
+ this.owner.window.hideThrobber();
+ if (!this.check(code)) { return; }
+ if (this.fromXML(data)) {
+ this.owner.alignTables();
+ }
+}
+
+/* --------------------- table manager ------------ */
+
+SQL.TableManager = OZ.Class();
+
+SQL.TableManager.prototype.init = function(owner) {
+ this.owner = owner;
+ this.dom = {
+ container:OZ.$("table"),
+ name:OZ.$("tablename"),
+ comment:OZ.$("tablecomment")
+ };
+ this.selected = null;
+ this.adding = false;
+
+ var ids = ["addtable","removetable","aligntables","cleartables","addrow","edittable","tablekeys"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ this.dom[id] = elm;
+ elm.value = _(id);
+ }
+
+ var ids = ["tablenamelabel","tablecommentlabel"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ elm.innerHTML = _(id);
+ }
+
+
+ this.select(false);
+
+ this.save = this.bind(this.save);
+
+ OZ.Event.add("area", "click", this.bind(this.click));
+ OZ.Event.add(this.dom.addtable, "click", this.bind(this.preAdd));
+ OZ.Event.add(this.dom.removetable, "click", this.bind(this.remove));
+ OZ.Event.add(this.dom.cleartables, "click", this.bind(this.clear));
+ OZ.Event.add(this.dom.addrow, "click", this.bind(this.addRow));
+ OZ.Event.add(this.dom.aligntables, "click", this.owner.bind(this.owner.alignTables));
+ OZ.Event.add(this.dom.edittable, "click", this.bind(this.edit));
+ OZ.Event.add(this.dom.tablekeys, "click", this.bind(this.keys));
+
+ this.dom.container.parentNode.removeChild(this.dom.container);
+}
+
+SQL.TableManager.prototype.addRow = function(e) {
+ var newrow = this.selected.addRow(_("newrow"));
+ this.owner.rowManager.select(newrow);
+}
+
+SQL.TableManager.prototype.select = function(table) { /* activate table */
+ if (this.selected === table) { return; }
+ this.selected = table;
+
+ var tables = this.owner.tables;
+ for (var i=0;i<tables.length;i++) {
+ tables[i].deselect();
+ }
+ if (this.selected) {
+ this.dom.removetable.disabled = false;
+ this.dom.addrow.disabled = false;
+ this.dom.edittable.disabled = false;
+ this.dom.tablekeys.disabled = false;
+ this.owner.raise(this.selected);
+ this.selected.select();
+ } else {
+ this.dom.removetable.disabled = true;
+ this.dom.addrow.disabled = true;
+ this.dom.edittable.disabled = true;
+ this.dom.tablekeys.disabled = true;
+ }
+}
+
+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.selected) { 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 result = confirm(_("confirmtable")+" '"+this.selected.getTitle()+"' ?");
+ if (!result) { return; }
+ this.owner.removeTable(this.selected);
+}
+
+SQL.TableManager.prototype.edit = function(e) {
+ this.owner.window.open(_("edittable"), this.dom.container, this.save);
+ this.dom.name.value = this.selected.getTitle();
+ this.dom.comment.value = this.selected.getComment();
+}
+
+SQL.TableManager.prototype.keys = function(e) { /* open keys dialog */
+ this.owner.keyManager.open(this.selected);
+}
+
+SQL.TableManager.prototype.save = function() {
+ this.selected.setTitle(this.dom.name.value);
+ this.selected.setComment(this.dom.comment.value);
+}
+
+/* --------------------- row manager ------------ */
+
+SQL.RowManager = OZ.Class();
+
+SQL.RowManager.prototype.init = function(owner) {
+ this.owner = owner;
+ this.dom = {};
+ this.selected = null;
+ this.creating = false;
+
+ var ids = ["editrow","removerow","uprow","downrow","foreigncreate"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ this.dom[id] = elm;
+ elm.value = _(id);
+ }
+
+ this.select(false);
+
+ OZ.Event.add(this.dom.editrow, "click", this.bind(this.edit));
+ OZ.Event.add(this.dom.uprow, "click", this.bind(this.up));
+ OZ.Event.add(this.dom.downrow, "click", this.bind(this.down));
+ OZ.Event.add(this.dom.removerow, "click", this.bind(this.remove));
+ OZ.Event.add(this.dom.foreigncreate, "click", this.bind(this.foreign));
+ OZ.Event.add(false, "tableclick", this.bind(this.tableClick));
+ OZ.Event.add(document, "keydown", this.bind(this.press));
+}
+
+SQL.RowManager.prototype.select = function(row) { /* activate a row */
+ if (this.selected === row) { return; }
+ if (this.selected) { this.selected.deselect(); }
+
+ this.selected = row;
+ if (this.selected) { this.selected.select(); }
+ this.redraw();
+}
+
+SQL.RowManager.prototype.tableClick = function(e) { /* create relation after clicking target table */
+ if (!this.creating) { return; }
+
+ var r1 = this.selected;
+ var t2 = e.target;
+
+ var p = this.owner.getOption("pattern");
+ p = p.replace(/%T/g,r1.owner.getTitle());
+ p = p.replace(/%t/g,t2.getTitle());
+ p = p.replace(/%R/g,r1.getTitle());
+
+ var r2 = t2.addRow(p, r1.data);
+ r2.update({"ai":false});
+ this.owner.addRelation(r1, r2);
+}
+
+SQL.RowManager.prototype.foreign = function(e) { /* start creating fk */
+ if (this.creating) {
+ this.endCreate();
+ } else {
+ this.creating = true;
+ this.dom.foreigncreate.value = "["+_("foreignpending")+"]";
+ }
+}
+
+SQL.RowManager.prototype.endCreate = function() {
+ this.creating = false;
+ this.dom.foreigncreate.value = _("foreigncreate");
+}
+
+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() {
+ 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.isPrimary());
+ } else {
+ this.endCreate();
+ this.dom.uprow.disabled = true;
+ this.dom.downrow.disabled = true;
+ this.dom.removerow.disabled = true;
+ this.dom.editrow.disabled = true;
+ this.dom.foreigncreate.disabled = true;
+ }
+}
+
+SQL.RowManager.prototype.press = function(e) {
+ if (!this.selected) { return; }
+ switch (e.keyCode) {
+ case 38:
+ this.up();
+ OZ.Event.prevent(e);
+ break;
+ case 40:
+ this.down();
+ OZ.Event.prevent(e);
+ break;
+ case 13:
+ case 27:
+ this.selected.collapse();
+ break;
+ }
+}
+
+SQL.RowManager.prototype.edit = function(e) {
+ this.selected.expand();
+}
+
+/* ----------------- key manager ---------- */
+
+SQL.KeyManager = OZ.Class();
+
+SQL.KeyManager.prototype.init = function(owner) {
+ this.owner = owner;
+ this.dom = {
+ container:OZ.$("keys")
+ }
+ this.build();
+}
+
+SQL.KeyManager.prototype.build = function() {
+ this.dom.list = OZ.$("keyslist");
+ this.dom.type = OZ.$("keytype");
+ this.dom.name = OZ.$("keyname");
+ this.dom.left = OZ.$("keyleft");
+ this.dom.right = OZ.$("keyright");
+ this.dom.fields = OZ.$("keyfields");
+ this.dom.avail = OZ.$("keyavail");
+ this.dom.listlabel = OZ.$("keyslistlabel");
+
+ var ids = ["keyadd","keyremove"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ this.dom[id] = elm;
+ elm.value = _(id);
+ }
+
+ var ids = ["keyedit","keytypelabel","keynamelabel","keyfieldslabel","keyavaillabel"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ elm.innerHTML = _(id);
+ }
+
+ var types = ["PRIMARY","INDEX","UNIQUE","FULLTEXT"];
+ for (var i=0;i<types.length;i++) {
+ var o = OZ.DOM.elm("option");
+ o.innerHTML = types[i];
+ o.value = types[i];
+ this.dom.type.appendChild(o);
+ }
+
+ OZ.Event.add(this.dom.list, "change", this.bind(this.listchange));
+ OZ.Event.add(this.dom.type, "change", this.bind(this.typechange));
+ OZ.Event.add(this.dom.name, "keyup", this.bind(this.namechange));
+ OZ.Event.add(this.dom.keyadd, "click", this.bind(this.add));
+ OZ.Event.add(this.dom.keyremove, "click", this.bind(this.remove));
+ OZ.Event.add(this.dom.left, "click", this.bind(this.left));
+ OZ.Event.add(this.dom.right, "click", this.bind(this.right));
+
+ this.dom.container.parentNode.removeChild(this.dom.container);
+}
+
+SQL.KeyManager.prototype.listchange = function(e) {
+ this.switchTo(this.dom.list.selectedIndex);
+}
+
+SQL.KeyManager.prototype.typechange = function(e) {
+ this.key.setType(this.dom.type.value);
+ this.redrawListItem();
+}
+
+SQL.KeyManager.prototype.namechange = function(e) {
+ this.key.setName(this.dom.name.value);
+ this.redrawListItem();
+}
+
+SQL.KeyManager.prototype.add = function(e) {
+ var type = (this.table.keys.length ? "INDEX" : "PRIMARY");
+ this.table.addKey(type);
+ this.sync(this.table);
+ this.switchTo(this.table.keys.length-1);
+}
+
+SQL.KeyManager.prototype.remove = function(e) {
+ var index = this.dom.list.selectedIndex;
+ if (index == -1) { return; }
+ var r = this.table.keys[index];
+ this.table.removeKey(r);
+ this.sync(this.table);
+}
+
+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<table.keys.length;i++) {
+ var k = table.keys[i];
+ var o = OZ.DOM.elm("option");
+ this.dom.list.appendChild(o);
+ var str = (i+1)+": "+k.getLabel();
+ o.innerHTML = str;
+ }
+ if (table.keys.length) {
+ this.switchTo(0);
+ } else {
+ this.disable();
+ }
+}
+
+SQL.KeyManager.prototype.redrawListItem = function() {
+ var index = this.table.keys.indexOf(this.key);
+ this.option.innerHTML = (index+1)+": "+this.key.getLabel();
+}
+
+SQL.KeyManager.prototype.switchTo = function(index) { /* show Nth key */
+ this.enable();
+ var k = this.table.keys[index];
+ this.key = k;
+ this.option = this.dom.list.getElementsByTagName("option")[index];
+
+ this.dom.list.selectedIndex = index;
+ this.dom.name.value = k.getName();
+
+ var opts = this.dom.type.getElementsByTagName("option");
+ for (var i=0;i<opts.length;i++) {
+ if (opts[i].value == k.getType()) { this.dom.type.selectedIndex = i; }
+ }
+
+ OZ.DOM.clear(this.dom.fields);
+ for (var i=0;i<k.rows.length;i++) {
+ var o = OZ.DOM.elm("option");
+ o.innerHTML = k.rows[i].getTitle();
+ o.value = o.innerHTML;
+ this.dom.fields.appendChild(o);
+ }
+
+ OZ.DOM.clear(this.dom.avail);
+ for (var i=0;i<this.table.rows.length;i++) {
+ var r = this.table.rows[i];
+ if (k.rows.indexOf(r) != -1) { continue; }
+ var o = OZ.DOM.elm("option");
+ o.innerHTML = r.getTitle();
+ o.value = o.innerHTML;
+ this.dom.avail.appendChild(o);
+ }
+}
+
+SQL.KeyManager.prototype.disable = function() {
+ OZ.DOM.clear(this.dom.fields);
+ OZ.DOM.clear(this.dom.avail);
+ this.dom.keyremove.disabled = true;
+ this.dom.left.disabled = true;
+ this.dom.right.disabled = true;
+ this.dom.list.disabled = true;
+ this.dom.name.disabled = true;
+ this.dom.type.disabled = true;
+ this.dom.fields.disabled = true;
+ this.dom.avail.disabled = true;
+}
+
+SQL.KeyManager.prototype.enable = function() {
+ this.dom.keyremove.disabled = false;
+ this.dom.left.disabled = false;
+ this.dom.right.disabled = false;
+ this.dom.list.disabled = false;
+ this.dom.name.disabled = false;
+ this.dom.type.disabled = false;
+ this.dom.fields.disabled = false;
+ this.dom.avail.disabled = false;
+}
+
+SQL.KeyManager.prototype.left = function(e) { /* add field to index */
+ var opts = this.dom.avail.getElementsByTagName("option");
+ for (var i=0;i<opts.length;i++) {
+ var o = opts[i];
+ if (o.selected) {
+ var row = this.table.findNamedRow(o.value);
+ this.key.addRow(row);
+ }
+ }
+ this.switchTo(this.dom.list.selectedIndex);
+}
+
+SQL.KeyManager.prototype.right = function(e) { /* remove field from index */
+ var opts = this.dom.fields.getElementsByTagName("option");
+ for (var i=0;i<opts.length;i++) {
+ var o = opts[i];
+ if (o.selected) {
+ var row = this.table.findNamedRow(o.value);
+ this.key.removeRow(row);
+ }
+ }
+ this.switchTo(this.dom.list.selectedIndex);
+}
+
+SQL.KeyManager.prototype.open = function(table) {
+ this.sync(table);
+ this.owner.window.open(_("tablekeys"),this.dom.container);
+}
+
+/* --------------------- window ------------ */
+
+SQL.Window = OZ.Class();
+
+SQL.Window.prototype.init = function(owner) {
+ this.owner = owner;
+ this.dom = {
+ container:OZ.$("window"),
+ background:OZ.$("background"),
+ ok:OZ.$("windowok"),
+ cancel:OZ.$("windowcancel"),
+ title:OZ.$("windowtitle"),
+ content:OZ.$("windowcontent"),
+ throbber:OZ.$("throbber")
+ }
+ this.dom.ok.value = _("windowok");
+ this.dom.cancel.value = _("windowcancel");
+ this.dom.throbber.alt = this.dom.throbber.title = _("throbber");
+ OZ.Event.add(this.dom.ok, "click", this.bind(this.ok));
+ OZ.Event.add(this.dom.cancel, "click", this.bind(this.close));
+ OZ.Event.add(document, "keydown", this.bind(this.key));
+
+ this.sync = this.bind(this.sync);
+
+ OZ.Event.add(window, "scroll", this.sync);
+ OZ.Event.add(window, "resize", this.sync);
+ this.state = 0;
+ this.hideThrobber();
+
+ this.sync();
+}
+
+SQL.Window.prototype.showThrobber = function() {
+ this.dom.throbber.style.visibility = "";
+}
+
+SQL.Window.prototype.hideThrobber = function() {
+ this.dom.throbber.style.visibility = "hidden";
+}
+
+SQL.Window.prototype.open = function(title, content, callback) {
+ this.state = 1;
+ this.callback = callback;
+ while (this.dom.title.childNodes.length > 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<all.length;i++) {
+ if (formElements.indexOf(all[i].tagName.toLowerCase()) != -1) {
+ all[i].focus();
+ break;
+ }
+ }
+}
+
+SQL.Window.prototype.key = function(e) {
+ if (!this.state) { return; }
+ if (e.keyCode == 13) { this.ok(e); }
+ if (e.keyCode == 27) { this.close(); }
+}
+
+SQL.Window.prototype.ok = function(e) {
+ if (this.callback) { this.callback(); }
+ this.close();
+}
+
+SQL.Window.prototype.close = function() {
+ if (!this.state) { return; }
+ this.state = 0;
+ this.dom.background.style.visibility = "hidden";
+ this.dom.container.style.visibility = "hidden";
+}
+
+SQL.Window.prototype.sync = function() { /* adjust background position */
+ var dims = OZ.DOM.win();
+ var scroll = OZ.DOM.scroll();
+ this.dom.background.style.width = dims[0]+"px";
+ this.dom.background.style.height = dims[1]+"px";
+ this.dom.background.style.left = scroll[0]+"px";
+ this.dom.background.style.top = scroll[1]+"px";
+}
+
+/* --------------------- options ------------ */
+
+SQL.Options = OZ.Class();
+
+SQL.Options.prototype.init = function(owner) {
+ this.owner = owner;
+ this.dom = {
+ container:OZ.$("opts"),
+ btn:OZ.$("options")
+ }
+ this.dom.btn.value = _("options");
+ this.save = this.bind(this.save);
+ this.build();
+}
+
+SQL.Options.prototype.build = function() {
+ this.dom.optionlocale = OZ.$("optionlocale");
+ this.dom.optiondb = OZ.$("optiondb");
+ this.dom.optionsnap = OZ.$("optionsnap");
+ this.dom.optionpattern = OZ.$("optionpattern");
+ this.dom.optionhide = OZ.$("optionhide");
+ this.dom.optionvector = OZ.$("optionvector");
+
+ var ids = ["language","db","snap","pattern","hide","vector","optionsnapnotice","optionpatternnotice","optionsnotice"];
+ for (var i=0;i<ids.length;i++) {
+ var id = ids[i];
+ var elm = OZ.$(id);
+ elm.innerHTML = _(id);
+ }
+
+ var ls = CONFIG.AVAILABLE_LOCALES;
+ for (var i=0;i<ls.length;i++) {
+ var o = OZ.DOM.elm("option");
+ o.value = ls[i];
+ o.innerHTML = ls[i];
+ this.dom.optionlocale.appendChild(o);
+ if (this.owner.getOption("locale") == ls[i]) { this.dom.optionlocale.selectedIndex = i; }
+ }
+
+ var dbs = CONFIG.AVAILABLE_DBS;
+ for (var i=0;i<dbs.length;i++) {
+ var o = OZ.DOM.elm("option");
+ o.value = dbs[i];
+ o.innerHTML = dbs[i];
+ this.dom.optiondb.appendChild(o);
+ if (this.owner.getOption("db") == dbs[i]) { this.dom.optiondb.selectedIndex = i; }
+ }
+
+
+ OZ.Event.add(this.dom.btn, "click", this.bind(this.click));
+
+ this.dom.container.parentNode.removeChild(this.dom.container);
+}
+
+SQL.Options.prototype.save = function() {
+ this.owner.setOption("locale",this.dom.optionlocale.value);
+ this.owner.setOption("db",this.dom.optiondb.value);
+ this.owner.setOption("snap",this.dom.optionsnap.value);
+ this.owner.setOption("pattern",this.dom.optionpattern.value);
+ this.owner.setOption("hide",this.dom.optionhide.checked ? "1" : "");
+ this.owner.setOption("vector",this.dom.optionvector.checked ? "1" : "");
+}
+
+SQL.Options.prototype.click = function() {
+ this.owner.window.open(_("options"),this.dom.container,this.save);
+ this.dom.optionsnap.value = this.owner.getOption("snap");
+ this.dom.optionpattern.value = this.owner.getOption("pattern");
+ this.dom.optionhide.checked = this.owner.getOption("hide");
+ this.dom.optionvector.checked = this.owner.getOption("vector");
+}
+
+/* --------------------- www sql designer ------------ */
+
+SQL.Designer = OZ.Class().extend(SQL.Visual);
+
+SQL.Designer.prototype.init = function() {
+ SQL.Designer = this;
+
+ this.tables = [];
+ this.relations = [];
+ this.title = document.title;
+
+ SQL.Visual.prototype.init.apply(this);
+
+ this.dom.container = this.dom.content = OZ.$("area");
+ this.width = this.dom.container.offsetWidth;
+ this.height = this.dom.container.offsetHeight;
+
+ this.flag = 2;
+
+ this.requestLanguage();
+ this.requestDB();
+
+ this.vector = this.getOption("vector") && (OZ.gecko || OZ.opera || OZ.safari || OZ.ie);
+ if (this.vector) {
+ this.vector = "svg";
+ if (OZ.ie) { this.vector = "vml"; }
+ }
+ if (this.vector == "svg") {
+ this.svgNS = "http://www.w3.org/2000/svg";
+ this.dom.svg = document.createElementNS(this.svgNS, "svg");
+ this.dom.svg.setAttribute("width",this.dom.container.offsetWidth);
+ this.dom.svg.setAttribute("height",this.dom.container.offsetHeight);
+ this.dom.content.appendChild(this.dom.svg);
+ }
+}
+
+SQL.Designer.prototype.requestLanguage = function() { /* get locale file */
+ var lang = this.getOption("locale")
+ var url = "locale/"+lang+".xml";
+ OZ.Request(url, this.bind(this.languageResponse), {method:"get", xml:true});
+}
+
+SQL.Designer.prototype.languageResponse = function(xmlDoc) {
+ if (xmlDoc) {
+ var strings = xmlDoc.getElementsByTagName("string");
+ for (var i=0;i<strings.length;i++) {
+ var n = strings[i].getAttribute("name");
+ var v = strings[i].firstChild.nodeValue;
+ window.LOCALE[n] = v;
+ }
+ }
+ this.flag--;
+ if (!this.flag) { this.init2(); }
+}
+
+SQL.Designer.prototype.requestDB = function() { /* get datatypes file */
+ var db = this.getOption("db");
+ var url = "db/"+db+"/datatypes.xml";
+ OZ.Request(url, this.bind(this.dbResponse), {method:"get", xml:true});
+}
+
+SQL.Designer.prototype.dbResponse = function(xmlDoc) {
+ if (xmlDoc) {
+ window.DATATYPES = xmlDoc.documentElement;
+ }
+ this.flag--;
+ if (!this.flag) { this.init2(); }
+}
+
+SQL.Designer.prototype.init2 = function() { /* secondary init, after locale & datatypes were retrieved */
+ this.map = new SQL.Map(this);
+ this.tableManager = new SQL.TableManager(this);
+ this.rowManager = new SQL.RowManager(this);
+ this.keyManager = new SQL.KeyManager(this);
+ this.io = new SQL.IO(this);
+ this.options = new SQL.Options(this);
+ this.window = new SQL.Window(this);
+
+ OZ.$("docs").value = _("docs");
+
+ var url = window.location.href;
+ var r = url.match(/keyword=([^&]+)/);
+ if (r) {
+ var keyword = r[1];
+ this.io.serverload(false, keyword);
+ }
+ document.body.style.visibility = "visible";
+}
+
+SQL.Designer.prototype.getMaxZ = function() { /* find max zIndex */
+ var max = 0;
+ for (var i=0;i<this.tables.length;i++) {
+ var z = this.tables[i].getZ();
+ if (z > max) { max = z; }
+ }
+ 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<parts.length;i++) {
+ var part = parts[i];
+ var r = part.match(/wwwsqldesigner=({.*?})/);
+ if (r) { obj = eval("("+r[1]+")"); }
+ }
+ return obj;
+}
+
+SQL.Designer.prototype.setCookie = function(obj) {
+ var arr = [];
+ for (var p in obj) {
+ arr.push(p+":'"+obj[p]+"'");
+ }
+ var str = "{"+arr.join(",")+"}";
+ document.cookie = "wwwsqldesigner="+str+"; path=/";
+}
+
+SQL.Designer.prototype.getOption = function(name) {
+ var c = this.getCookie();
+ if (name in c) { return c[name]; }
+ /* defaults */
+ switch (name) {
+ case "locale": return CONFIG.DEFAULT_LOCALE;
+ case "db": return CONFIG.DEFAULT_DB;
+ case "snap": return 0;
+ case "pattern": return "%R_%T";
+ case "hide": return false;
+ case "vector": return true;
+ default: return null;
+ }
+}
+
+SQL.Designer.prototype.setOption = function(name, value) {
+ var obj = this.getCookie();
+ obj[name] = value;
+ this.setCookie(obj);
+}
+
+SQL.Designer.prototype.raise = function(table) { /* raise a table */
+ var old = table.getZ();
+ var max = this.getMaxZ();
+ table.setZ(max);
+ for (var i=0;i<this.tables.length;i++) {
+ var t = this.tables[i];
+ if (t == table) { continue; }
+ if (t.getZ() > 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<this.tables.length;i++) {
+ var t = this.tables[i];
+ var w = t.dom.container.offsetWidth;
+ var h = t.dom.container.offsetHeight;
+ if (x + w > avail) {
+ x = 10;
+ y += 10 + max;
+ max = 0;
+ }
+ t.moveTo(x,y);
+ x += 10 + w;
+ if (h > max) { max = h; }
+ }
+}
+
+SQL.Designer.prototype.findNamedTable = function(name) { /* find row specified as table(row) */
+ for (var i=0;i<this.tables.length;i++) {
+ if (this.tables[i].getTitle() == name) { return this.tables[i]; }
+ }
+}
+
+SQL.Designer.prototype.toXML = function() {
+ var xml = '<?xml version="1.0" encoding="utf-8" ?>';
+ xml += '<sql>';
+
+ /* 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<this.tables.length;i++) {
+ xml += this.tables[i].toXML();
+ }
+ xml += "</sql>";
+ return xml;
+}
+
+SQL.Designer.prototype.fromXML = function(node) {
+ this.clearTables();
+ var types = node.getElementsByTagName("datatypes");
+ if (types.length) { window.DATATYPES = types[0]; }
+ var tables = node.getElementsByTagName("table");
+ for (var i=0;i<tables.length;i++) {
+ var t = this.addTable("", 0, 0);
+ t.fromXML(tables[i]);
+ }
+
+ /* relations */
+ var rs = node.getElementsByTagName("relation");
+ for (var i=0;i<rs.length;i++) {
+ var rel = rs[i];
+ var tname = rel.getAttribute("table");
+ var rname = rel.getAttribute("row");
+
+ var t1 = this.findNamedTable(tname);
+ if (!t1) { continue; }
+ var r1 = t1.findNamedRow(rname);
+ if (!r1) { continue; }
+
+ tname = rel.parentNode.parentNode.getAttribute("name");
+ rname = rel.parentNode.getAttribute("name");
+ var t2 = this.findNamedTable(tname);
+ if (!t2) { continue; }
+ var r2 = t2.findNamedRow(rname);
+ if (!r2) { continue; }
+
+ this.addRelation(r1, r2);
+ }
+}
+
+SQL.Designer.prototype.setTitle = function(t) {
+ document.title = this.title + (t ? " - "+t : "");
+}
+
+SQL.Designer.prototype.removeSelection = function() {
+ var sel = (window.getSelection ? window.getSelection() : document.selection);
+ if (!sel) { return; }
+ if (sel.empty) { sel.empty(); }
+ if (sel.removeAllRanges) { sel.removeAllRanges(); }
+}
diff --git a/locale/cs.xml b/locale/cs.xml
new file mode 100644
index 0000000..9aa7dcf
--- /dev/null
+++ b/locale/cs.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Přidat tabulku</string>
+ <string name="edittable">Upravit tabulku</string>
+ <string name="removetable">Smazat tabulku</string>
+ <string name="aligntables">Srovnat tabulky</string>
+ <string name="cleartables">Zrušit tabulky</string>
+ <string name="confirmall">Opravdu zrušit všechny tabulky</string>
+ <string name="newtable">nová tabulka</string>
+ <string name="addpending">umístit tabulku</string>
+ <string name="tablenamelabel">Jméno</string>
+ <string name="tablecommentlabel">Komentář</string>
+
+ <!-- row management -->
+ <string name="addrow">Přidat položku</string>
+ <string name="editrow">Upravit položku</string>
+ <string name="removerow">Smazat položku</string>
+ <string name="uprow">Nahoru</string>
+ <string name="downrow">Dolů</string>
+ <string name="newrow">nová položk</string>
+ <string name="foreigncreate">Vyrobit cizí klíč</string>
+ <string name="foreignpending">klikni na cílovou tabulku</string>
+ <string name="confirmtable">Opravdu smazat tabulku</string>
+ <string name="confirmrow">Opravdu smazat položku</string>
+
+ <!-- row edit -->
+ <string name="name">Jméno</string>
+ <string name="type">Typ</string>
+ <string name="size">Velikost</string>
+ <string name="def">Výchozí</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Autoincrement</string>
+ <string name="comment">Upravit komentář</string>
+ <string name="commenttext">VLožte komentář pro tuto položku</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Storno</string>
+ <string name="throbber">Prosím čekejte...</string>
+ <string name="options">Nastavení</string>
+ <string name="language">Jazyk</string>
+ <string name="db">Databáze pro nová schémata</string>
+ <string name="optionsnotice">Některá nastavení se projeví až po znovunačtení stránky. Aby nastavení fungovala, je nutné mít zapnuté cookies.</string>
+ <string name="snap">Vzdálenost přichytávání tabulek</string>
+ <string name="optionsnapnotice">V pixelech, 0 = bez přichytávání</string>
+ <string name="pattern">Vzor pro cizí jména</string>
+ <string name="optionpatternnotice">%T = primární tabulka, %R = primární klíč, %t = cizí tabulka</string>
+ <string name="hide">Schovat spojovníky při tažení tabulkou?</string>
+ <string name="vector">Vykreslovat oblé spojovníky (pakliže to prohlížeč podporuje)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Klíče</string>
+ <string name="keyslistlabel">Klíče v tabulce "%s"</string>
+ <string name="keytypelabel">Typ:</string>
+ <string name="keynamelabel">Název:</string>
+ <string name="keyfieldslabel">Položky v klíči</string>
+ <string name="keyavaillabel">Dostupné položky</string>
+ <string name="keyedit">Upravit klíč</string>
+ <string name="keyadd">Přidat klíč</string>
+ <string name="keyremove">Smazat klíč</string>
+
+ <!-- io -->
+ <string name="saveload">Uložit / Načíst</string>
+ <string name="empty">Prosím vložte XML data do textového pole níže.</string>
+ <string name="client">Klient</string>
+ <string name="server">Server</string>
+ <string name="output">Vstup / Výstup</string>
+ <string name="clientsave">Uložit XML</string>
+ <string name="clientload">Načíst XML</string>
+ <string name="clientsql">Generovat SQL</string>
+ <string name="backendlabel">Server backend:</string>
+ <string name="serversave">Uložit</string>
+ <string name="serverload">Načíst</string>
+ <string name="serverlist">Vypsat položky</string>
+ <string name="serverimport">Importovat z databáze</string>
+ <string name="serverloadprompt">Zadejte označení, pod kterým bylo vaše schéma uloženo:</string>
+ <string name="serversaveprompt">Zadejte označení, pod kterým bude vaše schéma uloženo:</string>
+ <string name="serverimportprompt">Zadejte název databáze k importu:</string>
+ <string name="httpresponse">Odpověď od serveru</string>
+ <string name="http201">Uloženo</string>
+ <string name="http404">Neexistuje</string>
+ <string name="http500">Vnitřní chyba serveru</string>
+ <string name="http501">Není implementováno</string>
+ <string name="http503">Služba není dostupná</string>
+
+ <!-- misc -->
+ <string name="xmlerror">XML chyba</string>
+ <string name="docs">Dokumentace</string>
+
+</locale>
diff --git a/locale/de.xml b/locale/de.xml
new file mode 100644
index 0000000..ff60cb1
--- /dev/null
+++ b/locale/de.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Tabelle hinzufügen</string>
+ <string name="edittable">Tabelle bearbeiten</string>
+ <string name="removetable">Tabelle entfernen</string>
+ <string name="aligntables">Tabellen ausrichten</string>
+ <string name="cleartables">Tabellen löschen</string>
+ <string name="confirmall">Wirklich alle Tabellen löschen</string>
+ <string name="newtable">Neue Tabelle</string>
+ <string name="addpending">Tabelle plazieren</string>
+ <string name="tablenamelabel">Name</string>
+ <string name="tablecommentlabel">Kommentar</string>
+
+ <!-- row management -->
+ <string name="addrow">Feld hinzufügen</string>
+ <string name="editrow">Feld bearbeiten</string>
+ <string name="removerow">Feld entfernen</string>
+ <string name="uprow">Hoch</string>
+ <string name="downrow">Runter</string>
+ <string name="newrow">Neues Feld</string>
+ <string name="foreigncreate">Fremdschlüssel erstellen</string>
+ <string name="foreignpending">Ziel-Tabelle wählen</string>
+ <string name="confirmtable">Tabelle wirklich löschen</string>
+ <string name="confirmrow">Feld wirklich löschen</string>
+
+ <!-- row edit -->
+ <string name="name">Name</string>
+ <string name="type">Typ</string>
+ <string name="size">Größe</string>
+ <string name="def">Default</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Autoincrement</string>
+ <string name="comment">Kommentar bearbeiten</string>
+ <string name="commenttext">Kommentar zu diesem Feld eintragen:</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Abbrechen</string>
+ <string name="throbber">Bitte warten...</string>
+ <string name="options">Einstellungen</string>
+ <string name="language">Sprache</string>
+ <string name="db">Datenbank für neue Diagramme</string>
+ <string name="optionsnotice">Einige Optionen werden erst nach einem erneutem Seitenaufruf wirksam. Cookies müssen aktiviert sein.</string>
+ <string name="snap">Tabellen Ausrichtungsabstand</string>
+ <string name="optionsnapnotice">in Pixel, 0 = einrasten deaktivieren</string>
+ <string name="pattern">Format für die Namen der Fremdschlüssel</string>
+ <string name="optionpatternnotice">%T = Primärtabelle, %R = Primärschlüssel, %t = Fremdtabelle</string>
+ <string name="hide">Verstecke Verbindungslinien beim bewegen von Tabellen?</string>
+ <string name="vector">Zeichne gegrümmte Verbindungslinien (Browser abhängig)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Schlüssel</string>
+ <string name="keyslistlabel">Schlüssel in Tabelle "%s"</string>
+ <string name="keytypelabel">Typ:</string>
+ <string name="keynamelabel">Name:</string>
+ <string name="keyfieldslabel">Felder im Schlüssel</string>
+ <string name="keyavaillabel">Verfügbare Felder</string>
+ <string name="keyedit">Schlüssel bearbeiten</string>
+ <string name="keyadd">Schlüssel hinzufügen</string>
+ <string name="keyremove">Schlüssel entfernen</string>
+
+ <!-- io -->
+ <string name="saveload">Speichern / Laden</string>
+ <string name="empty">Bitte fügen Sie die XML-Daten in das untere Textfeld ein und versuchen es erneut.</string>
+ <string name="client">Client</string>
+ <string name="server">Server</string>
+ <string name="output">Eingabe / Ausgabe</string>
+ <string name="clientsave">XML speichern</string>
+ <string name="clientload">XML laden</string>
+ <string name="clientsql">SQL erzeugen</string>
+ <string name="backendlabel">Server Basis:</string>
+ <string name="serversave">Speichern</string>
+ <string name="serverload">Laden</string>
+ <string name="serverlist">Einträge listen</string>
+ <string name="serverimport">Import aus DB</string>
+ <string name="serverloadprompt">Geben Sie das Stichwort ihres Diagramms ein, unter dem es gespeichert wurde:</string>
+ <string name="serversaveprompt">Geben Sie das Stichwort ihres Diagramms ein, unter dem es gespeichert werden soll:</string>
+ <string name="serverimportprompt">Geben Sie den Namen der zuimportierenden Datenbank ein:</string>
+ <string name="httpresponse">Server Antwort</string>
+ <string name="http201">gespeichert</string>
+ <string name="http404">Nicht gefunden</string>
+ <string name="http500">Interner Server Fehler</string>
+ <string name="http501">Nicht implementiert</string>
+ <string name="http503">Dienst nicht erreichbar</string>
+
+ <!-- misc -->
+ <string name="xmlerror">XML Fehler</string>
+ <string name="docs">Dokumentation</string>
+
+</locale>
diff --git a/locale/en.xml b/locale/en.xml
new file mode 100644
index 0000000..2286fb3
--- /dev/null
+++ b/locale/en.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Add table</string>
+ <string name="edittable">Edit table</string>
+ <string name="removetable">Remove table</string>
+ <string name="aligntables">Align tables</string>
+ <string name="cleartables">Clear tables</string>
+ <string name="confirmall">Really delete all tables</string>
+ <string name="newtable">new table</string>
+ <string name="addpending">place table</string>
+ <string name="tablenamelabel">Name</string>
+ <string name="tablecommentlabel">Comment</string>
+
+ <!-- row management -->
+ <string name="addrow">Add field</string>
+ <string name="editrow">Edit field</string>
+ <string name="removerow">Remove field</string>
+ <string name="uprow">Up</string>
+ <string name="downrow">Down</string>
+ <string name="newrow">new field</string>
+ <string name="foreigncreate">Create foreign key</string>
+ <string name="foreignpending">click target table</string>
+ <string name="confirmtable">Really delete table</string>
+ <string name="confirmrow">Really delete field</string>
+
+ <!-- row edit -->
+ <string name="name">Name</string>
+ <string name="type">Type</string>
+ <string name="size">Size</string>
+ <string name="def">Default</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Autoincrement</string>
+ <string name="comment">Edit comment</string>
+ <string name="commenttext">Enter comment for this field</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Cancel</string>
+ <string name="throbber">Please wait...</string>
+ <string name="options">Options</string>
+ <string name="language">Language</string>
+ <string name="db">Database for new designs</string>
+ <string name="optionsnotice">Some options are applied only after full page reload. Cookies must be enabled for options to work.</string>
+ <string name="snap">Table snap distance</string>
+ <string name="optionsnapnotice">In pixels, 0 = disable snapping</string>
+ <string name="pattern">Pattern for foreign names</string>
+ <string name="optionpatternnotice">%T = primary table, %R = primary key, %t = foreign table</string>
+ <string name="hide">Hide connectors on table drag?</string>
+ <string name="vector">Draw smooth connectors (if supported by browser)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Keys</string>
+ <string name="keyslistlabel">Keys in table "%s"</string>
+ <string name="keytypelabel">Type:</string>
+ <string name="keynamelabel">Name:</string>
+ <string name="keyfieldslabel">Fields in key</string>
+ <string name="keyavaillabel">Available fields</string>
+ <string name="keyedit">Edit key</string>
+ <string name="keyadd">Add key</string>
+ <string name="keyremove">Remove key</string>
+
+ <!-- io -->
+ <string name="saveload">Save / Load</string>
+ <string name="empty">Please paste XML data into the text area below and try again.</string>
+ <string name="client">Client</string>
+ <string name="server">Server</string>
+ <string name="output">Input / Output</string>
+ <string name="clientsave">Save XML</string>
+ <string name="clientload">Load XML</string>
+ <string name="clientsql">Generate SQL</string>
+ <string name="backendlabel">Server backend:</string>
+ <string name="serversave">Save</string>
+ <string name="serverload">Load</string>
+ <string name="serverlist">List items</string>
+ <string name="serverimport">Import from DB</string>
+ <string name="serverloadprompt">Enter keyword under which your design was saved:</string>
+ <string name="serversaveprompt">Enter keyword under which your design will be saved:</string>
+ <string name="serverimportprompt">Enter name of database to be imported:</string>
+ <string name="httpresponse">Server response</string>
+ <string name="http201">Saved</string>
+ <string name="http404">Not Found</string>
+ <string name="http500">Internal Server Error</string>
+ <string name="http501">Not Implemented</string>
+ <string name="http503">Service Unavailable</string>
+
+ <!-- misc -->
+ <string name="xmlerror">XML error</string>
+ <string name="docs">Documentation</string>
+
+</locale>
diff --git a/locale/es.xml b/locale/es.xml
new file mode 100644
index 0000000..214a8d7
--- /dev/null
+++ b/locale/es.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Agregar tabla</string>
+ <string name="edittable">Editar tabla</string>
+ <string name="removetable">Remover tabla</string>
+ <string name="aligntables">Alinear tablas</string>
+ <string name="cleartables">Limpiar tablas</string>
+ <string name="confirmall">Realmente borrar todas las tablas</string>
+ <string name="newtable">nueva tabla</string>
+ <string name="addpending">posicionar tabla</string>
+ <string name="tablenamelabel">Nombre</string>
+ <string name="tablecommentlabel">Comentario</string>
+
+ <!-- row management -->
+ <string name="addrow">Agregar campo</string>
+ <string name="editrow">Editar campo</string>
+ <string name="removerow">Remover campo</string>
+ <string name="uprow">Arriba</string>
+ <string name="downrow">Abajo</string>
+ <string name="newrow">nuevo campo</string>
+ <string name="foreigncreate">Crear llave foranea</string>
+ <string name="foreignpending">hacer clic en la tabla</string>
+ <string name="confirmtable">Realmente borrar tabla</string>
+ <string name="confirmrow">Realmente borrar campo</string>
+
+ <!-- row edit -->
+ <string name="name">Nombre</string>
+ <string name="type">Tipo</string>
+ <string name="size">Tamaño</string>
+ <string name="def">Valor por predeterminado</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Autoincremento</string>
+ <string name="comment">Editar comentario</string>
+ <string name="commenttext">Entrar comentario para este campo</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Cancelar</string>
+ <string name="throbber">Por favor esperar...</string>
+ <string name="options">Optiones</string>
+ <string name="language">Lenguaje</string>
+ <string name="db">Base de datos para nuevos diseños</string>
+ <string name="optionsnotice">Algunas optiones son aplicadas solo despues de recargar totalmente la pagina. Las Cookies deben estar habilidas para optiones de trabajo.</string>
+ <string name="snap">Tabla acceso remoto</string>
+ <string name="optionsnapnotice">En pixeles, 0 = deshabilitar acceso remoto</string>
+ <string name="pattern">Patron para nombres foraneos</string>
+ <string name="optionpatternnotice">%T = tabla primaria, %R = llave primaria, %t = tabla foranea</string>
+ <string name="hide">Esconder conectores en la tabla al arrastrar?</string>
+ <string name="vector">Dibujar conectores suave (si son soportados por el navegador)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Llaves</string>
+ <string name="keyslistlabel">Llaves en la tabla "%s"</string>
+ <string name="keytypelabel">Tipo:</string>
+ <string name="keynamelabel">Nombre:</string>
+ <string name="keyfieldslabel">Campos en la llave</string>
+ <string name="keyavaillabel">Campos disponibles</string>
+ <string name="keyedit">Editar llave</string>
+ <string name="keyadd">Agregar llave</string>
+ <string name="keyremove">Remover llave</string>
+
+ <!-- io -->
+ <string name="saveload">Guardar / Cargar</string>
+ <string name="empty">Favor de pegar el XML dentro del area de texto siguiente e intentar nuevamente.</string>
+ <string name="client">Cliente</string>
+ <string name="server">Servidor</string>
+ <string name="output">Entrada / Salida</string>
+ <string name="clientsave">Guardar XML</string>
+ <string name="clientload">Cargar XML</string>
+ <string name="clientsql">Generar SQL</string>
+ <string name="backendlabel">Servidor backend:</string>
+ <string name="serversave">Guardar</string>
+ <string name="serverload">Cargar</string>
+ <string name="serverlist">Lista de articulos</string>
+ <string name="serverimport">Importar desde BD</string>
+ <string name="serverloadprompt">Entrar palabra bajo la cual tu diseño fue guardado:</string>
+ <string name="serversaveprompt">Entrar palabra bajo la cual tu diseño va a ser guardado:</string>
+ <string name="serverimportprompt">Entrar nombre de base de datos a ser importada:</string>
+ <string name="httpresponse">Respuesta del servidor</string>
+ <string name="http201">Guardado</string>
+ <string name="http404">No Encontrado</string>
+ <string name="http500">Error Interno del Servidor</string>
+ <string name="http501">No Implementado</string>
+ <string name="http503">Servicio No Disponible</string>
+
+ <!-- misc -->
+ <string name="xmlerror">XML error</string>
+ <string name="docs">Documentacion</string>
+
+</locale>
diff --git a/locale/fr.xml b/locale/fr.xml
new file mode 100644
index 0000000..da6b38b
--- /dev/null
+++ b/locale/fr.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?><locale>
+ <!-- table management -->
+ <string name="addtable">Ajouter une table</string>
+ <string name="edittable">Éditer la table</string>
+ <string name="removetable">Supprimer la table</string>
+ <string name="aligntables">Aligner les tables</string>
+ <string name="cleartables">Supprimer les tables</string>
+ <string name="confirmall">Vraiment supprimer toutes les tables</string>
+ <string name="newtable">nouvelle table</string>
+ <string name="addpending">positionner la table</string>
+ <string name="tablenamelabel">Nom</string>
+ <string name="tablecommentlabel">Commentaire</string>
+
+ <!-- row management -->
+ <string name="addrow">Ajouter un champ</string>
+ <string name="editrow">Éditer un champ</string>
+ <string name="removerow">Supprimer le champ</string>
+ <string name="uprow">Remonter</string>
+ <string name="downrow">Descendre</string>
+ <string name="newrow">Éditer un champ</string>
+ <string name="foreigncreate">Créer une clé étrangère</string>
+ <string name="foreignpending">Cliquez la destination</string>
+ <string name="confirmtable">Voulez-vous vraiment supprimer cette table ?</string>
+ <string name="confirmrow">Voulez-vous vraiment supprimer ce champ ?</string>
+
+ <!-- row edit -->
+ <string name="name">Nom</string>
+ <string name="type">Type</string>
+ <string name="size">Taille</string>
+ <string name="def">Défaut</string>
+ <string name="notnull">NON NUL</string>
+ <string name="ai">Auto-incrémental</string>
+ <string name="comment">Éditer le commentaire</string>
+ <string name="commenttext">Saisir un commentaire à propos de ce champ</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Annuler</string>
+ <string name="throbber">Veuillez patienter...</string>
+ <string name="options">Options</string>
+ <string name="language">Langue</string>
+ <string name="db">Format des nouvelles base de données</string>
+ <string name="optionsnotice">Ces options ne seront appliquées qu'après le rafraichissement complet de la page. Les cookies doivent être autorisés.</string>
+ <string name="snap">Magnétisme des tables</string>
+ <string name="optionsnapnotice">En pixels, 0 = magnétisme désactivé</string>
+ <string name="pattern">Motif pour les noms de clés étrangères</string>
+ <string name="optionpatternnotice">%T = table primaire, %R = clé primaire, %t = table étrangère</string>
+ <string name="hide">Cacher les connecteurs lors du déplacement des tables ?</string>
+ <string name="vector">Dessiner des connecteurs « adoucis » (si le navigateur le supporte) ?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Clés</string>
+ <string name="keyslistlabel">Clés dans la table « %s »</string>
+ <string name="keytypelabel">Type :</string>
+ <string name="keynamelabel">Nom :</string>
+ <string name="keyfieldslabel">Champs de clé</string>
+ <string name="keyavaillabel">Champs disponibles</string>
+ <string name="keyedit">Éditer la clé</string>
+ <string name="keyadd">Ajouter une clé</string>
+ <string name="keyremove">Supprimer la clé</string>
+
+ <!-- io -->
+ <string name="saveload">Enregistrer / Charger</string>
+ <string name="empty">Merci de coller les données XML dans le champs prévu avant de ré-essayer.</string>
+ <string name="client">Client</string>
+ <string name="server">Serveur</string>
+ <string name="output">Entrée / Sortie</string>
+ <string name="clientsave">Enregistrer XML</string>
+ <string name="clientload">Charger XML</string>
+ <string name="clientsql">Génerer SQL</string>
+ <string name="backendlabel">Méthode du serveur :</string>
+ <string name="serversave">Enregistrer</string>
+ <string name="serverload">Charger</string>
+ <string name="serverlist">Éléments disponibles</string>
+ <string name="serverimport">Importer d'une base de données</string>
+ <string name="serverloadprompt">Saisir le mot-clé de votre schéma :</string>
+ <string name="serversaveprompt">Saisir un mot-clé pour sauvegarder votre schéma :</string>
+ <string name="serverimportprompt">Saisir le nom de la base de données à importer :</string>
+ <string name="httpresponse">Réponse du serveur</string>
+ <string name="http201">Sauvegardé</string>
+ <string name="http404">Introuvable</string>
+ <string name="http500">Erreur interne du serveur</string>
+ <string name="http501">Non Implementé</string>
+ <string name="http503">Service indisponible</string>
+
+ <!-- misc -->
+ <string name="xmlerror">Erreur XML</string>
+ <string name="docs">Documentation</string>
+
+</locale>
diff --git a/locale/pl.xml b/locale/pl.xml
new file mode 100644
index 0000000..ff85b7a
--- /dev/null
+++ b/locale/pl.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Dodaj tabelę</string>
+ <string name="edittable">Edytuj tabelę</string>
+ <string name="removetable">Usuń tabelę</string>
+ <string name="aligntables">Wyrównaj tabele</string>
+ <string name="cleartables">Wyczyść tabele</string>
+ <string name="confirmall">Czy na pewno usunąć wszystkie tabele</string>
+ <string name="newtable">nowa tabela</string>
+ <string name="addpending">miejsce tabeli</string>
+ <string name="tablenamelabel">Nazwa</string>
+ <string name="tablecommentlabel">Komentarz</string>
+
+ <!-- row management -->
+ <string name="addrow">Dodaj pole</string>
+ <string name="editrow">Edytuj pole</string>
+ <string name="removerow">Usuń pole</string>
+ <string name="uprow">W górę</string>
+ <string name="downrow">W dół</string>
+ <string name="newrow">nowe pole</string>
+ <string name="foreigncreate">Utwórz klucz zewnętrzny</string>
+ <string name="foreignpending">kliknij w docelową tabelę</string>
+ <string name="confirmtable">Czy na pewno usunąć tabelę</string>
+ <string name="confirmrow">Czy na pewno usunąć pole</string>
+
+ <!-- row edit -->
+ <string name="name">Nazwa</string>
+ <string name="type">Typ</string>
+ <string name="size">Rozmiar</string>
+ <string name="def">Domyślnie</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Autoincrement</string>
+ <string name="comment">Edytuj komentarz</string>
+ <string name="commenttext">Wpisz komentarz dla tego pola</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Anuluj</string>
+ <string name="throbber">Proszę czekać...</string>
+ <string name="options">Opcje</string>
+ <string name="language">Język</string>
+ <string name="db">Bazy danych dla nowych projektów</string>
+ <string name="optionsnotice">Niektóre opcje są zatwierdzane wyłącznie po kompletnym przeładowaniu strony. Ciasteczka muszą być akceptowane dla działania opcji.</string>
+ <string name="snap">Ustalana odległość tabel</string>
+ <string name="optionsnapnotice">W pikselach, 0 = wyłącznie ustalania</string>
+ <string name="pattern">Wzorzec dla zewnętrznych nazw</string>
+ <string name="optionpatternnotice">%T = główna tabela, %R = klucz główny, %t = zewnętrzna tabela</string>
+ <string name="hide">Ukryć złącza w tabeli podczas przeciągania?</string>
+ <string name="vector">Rysuj pływające złącza (jesli wsperane jest przez przeglądarkę)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Klucze</string>
+ <string name="keyslistlabel">Klucze w tabeli "%s"</string>
+ <string name="keytypelabel">Typ:</string>
+ <string name="keynamelabel">Nazwa:</string>
+ <string name="keyfieldslabel">Pola w kluczu</string>
+ <string name="keyavaillabel">Dostępne pola</string>
+ <string name="keyedit">Edytuj klucz</string>
+ <string name="keyadd">Dodaj klucz</string>
+ <string name="keyremove">Usuń klucz</string>
+
+ <!-- io -->
+ <string name="saveload">Zapisz / Otwórz</string>
+ <string name="empty">Proszę wklej kod XML w poniższe pole tekstowe i spróbuj ponownie.</string>
+ <string name="client">Klient</string>
+ <string name="server">Serwer</string>
+ <string name="output">Wejście / Wyjście</string>
+ <string name="clientsave">Zapisz XML</string>
+ <string name="clientload">Załaduj XML</string>
+ <string name="clientsql">Generuj SQL</string>
+ <string name="backendlabel">Serwer wejściowy:</string>
+ <string name="serversave">Zapisz</string>
+ <string name="serverload">Załaduj</string>
+ <string name="serverlist">Lista pozycji</string>
+ <string name="serverimport">Importuj z DB</string>
+ <string name="serverloadprompt">Wpisz słowo kluczowe pod którym twój projekt został zapisany:</string>
+ <string name="serversaveprompt">Wpisz słowo kluczowe pod którym twój projekt ma zostać zapisany:</string>
+ <string name="serverimportprompt">Wpisz nazwę bazy danych do zaimportowania:</string>
+ <string name="httpresponse">Odpowiedź serwera</string>
+ <string name="http201">Zapisano</string>
+ <string name="http404">Nie znaleniono</string>
+ <string name="http500">Wewnętrzny błąd serwera</string>
+ <string name="http501">Nie zaimplementowane</string>
+ <string name="http503">Serwer niedostępny</string>
+
+ <!-- misc -->
+ <string name="xmlerror">XML error</string>
+ <string name="docs">Dokumentacja</string>
+
+</locale>
diff --git a/locale/pt_BR.xml b/locale/pt_BR.xml
new file mode 100644
index 0000000..e490ef8
--- /dev/null
+++ b/locale/pt_BR.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale>
+ <!-- table management -->
+ <string name="addtable">Adicionar tabela</string>
+ <string name="edittable">Editar tabela</string>
+ <string name="removetable">Remover tabela</string>
+ <string name="aligntables">Alinhar tabelas</string>
+ <string name="cleartables">Limpar tabelas</string>
+ <string name="confirmall">Realmente excluir todas as tabelas</string>
+ <string name="newtable">Nova tabela</string>
+ <string name="addpending">Clique p/ adicionar</string>
+ <string name="tablenamelabel">Nome</string>
+ <string name="tablecommentlabel">Comentário</string>
+
+ <!-- row management -->
+ <string name="addrow">Adicionar campo</string>
+ <string name="editrow">Editar campo</string>
+ <string name="removerow">Remover campo</string>
+ <string name="uprow">Para cima</string>
+ <string name="downrow">Para baixo</string>
+ <string name="newrow">Novo campo</string>
+ <string name="foreigncreate">Criar chave estrangeira</string>
+ <string name="foreignpending">Selecione a tabela alvo(destino)</string>
+ <string name="confirmtable">Deseja realmente deletar a tabela</string>
+ <string name="confirmrow">Deseja realmente deletar o campo</string>
+
+ <!-- row edit -->
+ <string name="name">Nome</string>
+ <string name="type">Tipo</string>
+ <string name="size">Tamanho</string>
+ <string name="def">Default</string>
+ <string name="notnull">NOT NULL</string>
+ <string name="ai">Auto incrementar</string>
+ <string name="comment">Editar comentário</string>
+ <string name="commenttext">Digite o comentário para este campo</string>
+
+ <!-- windows & options -->
+ <string name="windowok">OK</string>
+ <string name="windowcancel">Cancelar</string>
+ <string name="throbber">Por favor espere...</string>
+ <string name="options">Opções</string>
+ <string name="language">Linguagem</string>
+ <string name="db">Base de Dados para os novos designs</string>
+ <string name="optionsnotice">Algumas opções serão aplicadas somente depois da página totalmente regarrecada. Cookies devem ser ativados para as opções funcionarem.</string>
+ <string name="snap">Distância entre as tabelas</string>
+ <string name="optionsnapnotice">Em pixels, 0 = desativar snapping</string>
+ <string name="pattern">Padrão p/ nomes estrangeiros</string>
+ <string name="optionpatternnotice">%T = tabela primária, %R = chave primária, %t = tabela estrangeira</string>
+ <string name="hide">Esconder connectores na tela?</string>
+ <string name="vector">Desenhar conectores suaves (se suportado pelo navegador)?</string>
+
+
+ <!-- keys -->
+ <string name="tablekeys">Chaves</string>
+ <string name="keyslistlabel">Chaves na tabela "%s"</string>
+ <string name="keytypelabel">Tipo:</string>
+ <string name="keynamelabel">Nome:</string>
+ <string name="keyfieldslabel">Campos na chave</string>
+ <string name="keyavaillabel">Campos disponíveis</string>
+ <string name="keyedit">Editar chave</string>
+ <string name="keyadd">Adicionar chave</string>
+ <string name="keyremove">Remover chave</string>
+
+ <!-- io -->
+ <string name="saveload">Salvar / Carregar</string>
+ <string name="empty">Por favor cole os dados XML na área de texto abaixo e tente novamente.</string>
+ <string name="client">Cliente</string>
+ <string name="server">Servidor</string>
+ <string name="output">Entrada / Saída</string>
+ <string name="clientsave">Salvar XML</string>
+ <string name="clientload">Carregar XML</string>
+ <string name="clientsql">Gerar SQL</string>
+ <string name="backendlabel"> Parâmetros do Servidor:</string>
+ <string name="serversave">Salvar</string>
+ <string name="serverload">Carregar</string>
+ <string name="serverlist">Listar itens</string>
+ <string name="serverimport">Importar do BD</string>
+ <string name="serverloadprompt">Digite o nome o qual seu design foi salvo:</string>
+ <string name="serversaveprompt">Digite o nome com qual seu design será salvo:</string>
+ <string name="serverimportprompt">Digite o nome da base de dados à ser importada:</string>
+ <string name="httpresponse"> Resposta do servidor</string>
+ <string name="http201">Salvo</string>
+ <string name="http404">Não Encontrado</string>
+ <string name="http500">Erro Interno do Servidor</string>
+ <string name="http501">Não Implementado</string>
+ <string name="http503">Serviço Indisponível</string>
+
+ <!-- misc -->
+ <string name="xmlerror">Erro de XML</string>
+ <string name="docs">Documentação</string>
+
+</locale>
diff --git a/styles/doc.css b/styles/doc.css
new file mode 100644
index 0000000..97d2025
--- /dev/null
+++ b/styles/doc.css
@@ -0,0 +1,19 @@
+body {
+ font-family: verdana;
+ font-size: 80%;
+}
+
+ul#changelog li {
+ font-weight: bold;
+ list-style-type: none;
+ margin-bottom: 1em;
+}
+
+ul#changelog li li {
+ font-weight: normal;
+ margin-bottom: 0em;
+}
+
+code {
+ font-size: 120%;
+}
diff --git a/styles/ie6.css b/styles/ie6.css
new file mode 100644
index 0000000..03de786
--- /dev/null
+++ b/styles/ie6.css
@@ -0,0 +1,58 @@
+v\:* {
+ behavior:url(#default#VML);
+}
+
+#bar {
+ position: absolute;
+ right: auto;
+ left: expression(eval(document.documentElement.scrollLeft)+document.documentElement.clientWidth-eval(this.offsetWidth));
+ top: expression(eval(document.documentElement.scrollTop));
+}
+
+#bar .shadow-corner {
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/bar_corner.png',sizingMethod='crop');
+ overflow: hidden;
+}
+
+#bar .shadow-left {
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/bar_left.png',sizingMethod='crop');
+ height: expression(eval(this.parentNode.offsetHeight));
+ overflow: hidden;
+}
+
+#bar .shadow-bottom {
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/bar_bottom.png',sizingMethod='crop');
+ width: expression(eval(this.parentNode.offsetWidth));
+ overflow: hidden;
+}
+
+.table .shadow-corner {
+ background-image: none;
+}
+
+.table .shadow-right {
+ background-image: none;
+}
+
+.table .shadow-bottom {
+ background-image: none;
+}
+
+#minimap {
+ filter: alpha(opacity=90);
+ position: absolute;
+ right: auto;
+ left: expression(eval(document.documentElement.scrollLeft)+document.documentElement.clientWidth-eval(this.offsetWidth));
+ top: expression(eval(document.documentElement.scrollTop)+document.documentElement.clientHeight-eval(this.offsetHeight));
+}
+
+#background {
+ filter: alpha(opacity=50);
+}
+
+#keys, #opts {
+ width: expression(eval(document.documentElement.clientWidth)/2);
+}
diff --git a/styles/ie7.css b/styles/ie7.css
new file mode 100644
index 0000000..b333f0f
--- /dev/null
+++ b/styles/ie7.css
@@ -0,0 +1,15 @@
+v\:* {
+ behavior:url(#default#VML);
+}
+
+#minimap {
+ filter: alpha(opacity=90);
+}
+
+#background {
+ filter: alpha(opacity=50);
+}
+
+#keys, #opts {
+ width: expression(eval(document.documentElement.clientWidth)/2);
+}
diff --git a/styles/print.css b/styles/print.css
new file mode 100644
index 0000000..d14052f
--- /dev/null
+++ b/styles/print.css
@@ -0,0 +1,3 @@
+#bar, #background {
+ display: none;
+} \ No newline at end of file
diff --git a/styles/style.css b/styles/style.css
new file mode 100644
index 0000000..032c51a
--- /dev/null
+++ b/styles/style.css
@@ -0,0 +1,229 @@
+body {
+ font-family: verdana, sans serif;
+ font-size: small;
+ padding: 0px;
+ margin: 0px;
+ background: url(../images/back.gif) fixed;
+ visibility: hidden;
+}
+
+#area {
+ z-index: 1;
+ width: 2000px;
+ height: 2000px;
+}
+
+#bar {
+ z-index: 100;
+ text-align: center;
+ background-color: #ccc;
+ position: fixed;
+ top: 0px;
+ right: 0px;
+ width: 150px;
+ padding: 5px;
+}
+
+#bar .shadow-corner {
+ width: 8px;
+ height: 8px;
+ position: absolute;
+ left: -8px;
+ bottom: -8px;
+ background-image: url(../images/bar_corner.png);
+}
+
+#bar .shadow-left {
+ width: 8px;
+ height: 100%;
+ position: absolute;
+ left: -8px;
+ top: 0px;
+ background-image: url(../images/bar_left.png);
+}
+
+#bar .shadow-bottom {
+ width: 100%;
+ height: 8px;
+ position: absolute;
+ left: 0px;
+ bottom: -8px;
+ background-image: url(../images/bar_bottom.png);
+}
+
+#bar input {
+ display: block;
+ width: 90%;
+ margin: auto;
+}
+
+#bar input.small {
+ width: 45%;
+ display: inline;
+}
+
+#minimap {
+ z-index: 100;
+ position: fixed;
+ width: 100px;
+ height: 100px;
+ right: 0px;
+ bottom: 0px;
+ background-color: #fff;
+ border: 1px solid #000;
+ opacity: 0.9;
+ overflow: hidden;
+}
+
+.mini {
+ position: absolute;
+ border: 1px solid #000;
+ background-color: #eea;
+ font-size: 1px;
+ line-height: 1px;
+}
+
+.mini_selected {
+ background-color: #f85;
+}
+
+.port {
+ position: absolute;
+ border: 2px solid #f00;
+}
+
+.table {
+ position: absolute;
+ border: 1px solid #000;
+ background-color: #ddd;
+ cursor: pointer;
+ z-index: 10;
+}
+
+.table .shadow-corner {
+ width: 8px;
+ height: 8px;
+ position: absolute;
+ right: -8px;
+ bottom: -8px;
+ background-image: url(../images/table_corner.png);
+}
+
+.table .shadow-right {
+ width: 8px;
+ height: 100%;
+ position: absolute;
+ right: -8px;
+ top: 0px;
+ background-image: url(../images/table_right.png);
+}
+
+.table .shadow-bottom {
+ width: 100%;
+ height: 8px;
+ position: absolute;
+ left: 0px;
+ bottom: -8px;
+ background-image: url(../images/table_bottom.png);
+}
+
+
+.table_selected {
+ border: 2px solid #000;
+}
+
+.table_title {
+ margin: 0px 30px;
+ text-align: center;
+ padding: 3px 0px;
+}
+
+.row {
+ border-top: 1px dotted #888;
+ padding: 3px;
+}
+
+.row_selected {
+ font-weight: bold;
+ color: #f00;
+ float: left;
+}
+
+.primary {
+ font-weight: bold;
+}
+
+.comment {
+ font-size: 80%;
+ font-weight: normal;
+ margin-right: 0.5em;
+}
+
+.adding {
+ cursor: crosshair;
+}
+
+.relation {
+ background-color: #000;
+ overflow: hidden;
+}
+
+#background {
+ position: absolute;
+ background-color: #000;
+ opacity: 0.5;
+ visibility: hidden;
+ z-index: 102;
+}
+
+#window {
+ position: absolute;
+ visibility: hidden;
+ z-index: 103;
+ background-color: #fff;
+ border: 6px double #333;
+}
+
+#windowtitle {
+ border-bottom: 2px solid #333;
+ padding: 2px;
+ padding-left: 1em;
+ font-weight: bold;
+ background-color: rgb(238, 238, 170);
+}
+
+#windowcontent {
+ padding: 1em;
+}
+
+#windowok, #windowcancel {
+ margin: 0em 1em 1em;
+}
+
+.small {
+ font-size: 85%;
+}
+
+#textarea {
+ width: 500px;
+ height: 100px;
+}
+
+#keys {
+ white-space: nowrap;
+ text-align: center;
+}
+
+legend {
+ font-weight: bold;
+}
+
+label, input, select {
+ vertical-align: middle;
+}
+
+#throbber {
+ position: absolute;
+ top: 2px;
+ right: 3px;
+} \ No newline at end of file