diff options
author | ondrej.zara <none@none> | 2008-12-04 08:13:14 +0000 |
---|---|---|
committer | ondrej.zara <none@none> | 2008-12-04 08:13:14 +0000 |
commit | 3e17dc90adcb2e93d9b3eb5f59adecb1c7981b84 (patch) | |
tree | 08d0f7d5f9cc5749e941bdebc63b8f9a2bffd537 | |
parent | 6bcb4d2789f2524b62a93c85bb3aae8c95d4f902 (diff) | |
download | wwwsqldesigner-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
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 & 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 Binary files differnew file mode 100644 index 0000000..4ac1255 --- /dev/null +++ b/backend/php-sqlite/wwwsqldesigner.sqlite 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 <= n" note="Variable-length data with a maximum of 8,000 characters" /> + <type label="Text" length="1" sql="text" quote="'" bytes="<= 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 <= n" note="Variable-length Unicode data with a maximum length of 4,000 characters" /> + <type label="nText" length="1" sql="ntext" quote="'" bytes="<= 2,147,483,647" note="Variable-length Unicode data with a maximum length of 1,073,741,823 characters" /> + </group> + + + <group label="Date & 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 <= 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 & 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='"'"' /> + <xsl:with-param name="to" select='"''"' /> + </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='"'"' /> + <xsl:with-param name="to" select='"''"' /> + </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 & 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='"'"' /> + <xsl:with-param name="to" select='"''"' /> + </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='"'"' /> + <xsl:with-param name="to" select='"''"' /> + </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 & 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 & 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&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&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>, © 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 & 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 <script></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 <label>s</li> + <li>* fixed non-selectable user-added rows (thanks to Paul Thrasher)</li> + <li>* added GNU GPL licence</li> + </ul> + </li> +</ul> +</body> @@ -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 Binary files differnew file mode 100644 index 0000000..0e93eaa --- /dev/null +++ b/images/back.gif diff --git a/images/bar_bottom.png b/images/bar_bottom.png Binary files differnew file mode 100644 index 0000000..bb361ee --- /dev/null +++ b/images/bar_bottom.png diff --git a/images/bar_corner.png b/images/bar_corner.png Binary files differnew file mode 100644 index 0000000..807c65c --- /dev/null +++ b/images/bar_corner.png diff --git a/images/bar_left.png b/images/bar_left.png Binary files differnew file mode 100644 index 0000000..ec7f34b --- /dev/null +++ b/images/bar_left.png diff --git a/images/table_bottom.png b/images/table_bottom.png Binary files differnew file mode 100644 index 0000000..0890c8e --- /dev/null +++ b/images/table_bottom.png diff --git a/images/table_corner.png b/images/table_corner.png Binary files differnew file mode 100644 index 0000000..e5e86de --- /dev/null +++ b/images/table_corner.png diff --git a/images/table_right.png b/images/table_right.png Binary files differnew file mode 100644 index 0000000..0f4600f --- /dev/null +++ b/images/table_right.png diff --git a/images/throbber.gif b/images/throbber.gif Binary files differnew file mode 100644 index 0000000..cce32f2 --- /dev/null +++ b/images/throbber.gif 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="<<" /><br/> + <input type="button" id="keyright" value=">>" /><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 = "» "; + + 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,"""); + 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, "&").replace(/>/g, ">").replace(/</g, "<"); + 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,"""); + 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, "&").replace(/>/g, ">").replace(/</g, "<"); + 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 |