├── LICENSE
├── README.md
├── Web-GUI-for-SQLite.css
├── Web-GUI-for-SQLite.html
├── Web-GUI-for-SQLite.js
├── external
├── a11y-dialog
│ ├── LICENSE
│ ├── README.md
│ ├── a11y-dialog.js
│ ├── a11y-dialog.min.js
│ └── package.json
├── codemirror
│ ├── LICENSE
│ ├── codemirror.css
│ ├── codemirror.js
│ └── mode
│ │ └── sql
│ │ ├── index.html
│ │ └── sql.js
└── sql
│ ├── AUTHORS
│ └── sql.js
├── image
├── error.png
├── minus.png
├── plus.png
├── preview.png
└── update.png
└── test
├── ci.js
├── config.js
├── package.json
├── test.csv
└── test.sqli
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 cyril bois (https://github.com/cyrilbois)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Web GUI for SQLite
2 |
3 | Web GUI for SQLite is a web-based SQLite browser written in JavaScript.
4 |
5 | This tool is still basic and needs to be improved.
6 |
7 | Try the demo here: [https://extendsclass.com/sqlite-browser.html](https://extendsclass.com/sqlite-browser.html)
8 |
9 | 
10 |
11 | ## Dependencies
12 |
13 | This tool required:
14 | * [a11y-dialog](https://github.com/edenspiekermann/a11y-dialog) (MIT license)
15 | * [codeMirror](https://github.com/codemirror/CodeMirror) (MIT license)
16 | * [sql.js](https://github.com/kripken/sql.js/) (MIT license)
17 | * [github corners](https://github.com/tholman/github-corners) (MIT license)
18 |
19 | ## Install
20 |
21 | Drop the files into a directory (on a server or on your PC) and then visit in a browser.
22 |
23 | ## Launch tests
24 |
25 | Update config.js file with the path of your installation.
26 |
27 | You must install packages:
28 | npm install
29 |
30 | Finally, runs the tests:
31 | npm run test
32 |
33 | ## License
34 |
35 | MIT
36 |
--------------------------------------------------------------------------------
/Web-GUI-for-SQLite.css:
--------------------------------------------------------------------------------
1 | body {margin:0; padding:0; font-family: Verdana, "Bitstream Vera Sans", "Lucida Grande", sans-serif;}
2 | header {margin:0; padding:0;background-color: #121212;min-height: 80px;}
3 | h1 {color: white;font-size: 3.1em;font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;font-weight: 900;text-align: center;margin: 0;}
4 | .SQLite-WebJS-body {}
5 | .SQLite-WebJS-results{margin: 0 auto; border:1px solid #bbbbbb;border-collapse:collapse;margin-top:16px;}
6 | .SQLite-WebJS-results td{padding:8px;margin:0px;border:0px;}
7 | .SQLite-WebJS-results tbody > tr > td, .SQLite-WebJS-results thead > tr > th, .SQLite-WebJS-results tfoot > tr > th{padding:8px;margin:0px;border:1px solid #bbbbbb;font-weight:bold;color:gray;text-align:center;}
8 | .SQLite-WebJS-results-odd{background-color:#E6E6E6;}
9 | .SQLite-WebJS-container-center {text-align:center;}
10 | .SQLite-WebJS-export-container{overflow-x:auto;white-space:nowrap;text-align:center;}
11 | .editor-message-container {height:38px;}
12 | .SQLite-WebJS-editor-error{color:red;padding:8px;background-color:#F6CECE;margin:10px 0px;}
13 | .SQLite-WebJS-editor-valid{color:green;padding:8px;background-color:#D0F5A9;margin:10px 0px;}
14 | .SQLite-WebJS-editor-inprogress{color:orange;padding:8px;background-color:#ffe680;margin:10px 0px;}
15 | .SQLite-WebJS-structure {border:2px solid #bbbbbb;padding:0px;margin-top:8px;padding:10px;}
16 | .SQLite-WebJS-container {float:right;width:67%;margin-left:2%;}
17 | .SQLite-WebJS-tabber {text-align:center;}
18 | .SQLite-WebJS-database {margin-top: 10px;margin-bottom: 10px;border: 1px solid #121212;word-wrap: break-word;text-align: left;float: left;width:30%; max-width: 400px;}
19 | .SQLite-WebJS-database-title {background-color: #121212;color: white;text-align: center;font-size: 17px;font-weight: bold;padding: 5px;}
20 | .SQLite-WebJS-database-container {padding:8px;}
21 | .SQLite-WebJS-browser-structure {font-size:17px;font-weight:bold;cursor:pointer;}
22 | .SQLite-WebJS-browser-img-click {max-width:15px;margin-right:12px;}
23 | .SQLite-WebJS-browser-update {max-width:40px;float:right;cursor:pointer;}
24 | .SQLite-WebJS-browser-canbeclick {cursor:pointer;margin-left:8px;margin-top:2px;margin-bottom:2px;}
25 | .SQLite-WebJS-browser-javascript-tabber {display:inline-block;}
26 | .SQLite-WebJS-button {cursor:pointer;font-size:13px;font-weight:bold;background:#fff;color:#000;border:1px solid #bbbbbb;cursor:pointer;text-decoration:none;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;padding:6px 18px;background-color:#121212;color:white;}
27 | .SQLite-WebJS-button :hover {background-color:gray;}
28 | .SQLite-WebJS-execute-query { float: right;}
29 | .SQLite-WebJS-editor-container{border:2px solid #bbbbbb;padding:0px;margin-top:8px;}
30 | .SQLite-WebJS-browser-javascript-tabber li{padding:8px;font-size:18px;font-weight:bold;background-color:white;display:inline-block;list-style:none;border:1 px solid gray;border-radius: 8px;margin-left:8px;margin-top:8px;cursor:pointer;}
31 | li.SQLite-WebJS-browser-javascript-tabber-select {font-weight:bold;background-color:#99ff99;}
32 | .SQLite-WebJS-container-row {max-height:600px;overflow: auto;}
33 | .SQLite-WebJS-browser-order {cursor:pointer;font-size:15px;}
34 | .SQLite-WebJS-scroll{overflow:auto;}
35 | nav.menu-intool {
36 | margin-top:2px;
37 | font-weight:bold;
38 | }
39 |
40 | nav.menu-intool ul {
41 | background: #121212;
42 | list-style: none;
43 | margin: 0;
44 | padding: 0;
45 | display: flex;flex-wrap: wrap;
46 | justify-content: center;
47 | text-align: center;
48 | }
49 | nav.menu-intool ul li {
50 | position: relative;
51 | display: inline-block;
52 | margin-right: -4px;
53 | text-align: center;
54 | }
55 | nav.menu-intool ul li:last-child {
56 | margin: 0;
57 | }
58 | nav.menu-intool ul li a {
59 | display: block;
60 | background: #121212;
61 | padding: 15px 20px;
62 | color: #fff;
63 | font-size: 1.1em;
64 | text-decoration: none;
65 | transition: 0.2s linear;
66 | }
67 | nav.menu-intool ul li a.sub-menu-important {
68 | color: #4DAF52;
69 | font-size: 1.2em;
70 | }
71 |
72 | nav.menu-intool ul li a:hover {
73 | background: gray;
74 | cursor:pointer;
75 | }
76 | nav.menu-intool ul li ul {
77 | position: absolute;
78 | top: 100%;
79 | left: 0;
80 | width: 240px;
81 | border-bottom: 4px solid #121212;
82 | flex-direction: column;
83 | display: flex;
84 |
85 | }
86 | nav.menu-intool ul li ul li {
87 | display: block;
88 | width: 100%;
89 | margin: 0;
90 | text-align: left;
91 | z-index: 1001;
92 | }
93 | nav.menu-intool ul li ul li a {
94 | display: block;
95 | background: #3a3a3a;
96 | padding: 10px 15px;
97 | }
98 | nav.menu-intool ul li ul li a:hover {
99 | background: gray;
100 | border-left: 4px solid #121212;
101 | }
102 | .arrow {
103 | border: solid white;
104 | border-width: 0 3px 3px 0;
105 | display: inline-block;
106 | padding: 3px;
107 | }
108 |
109 | .up {
110 | transform: rotate(-135deg);
111 | -webkit-transform: rotate(-135deg);
112 | }
113 |
114 | .down {
115 | transform: rotate(45deg);
116 | -webkit-transform: rotate(45deg);
117 | }
118 |
119 |
120 |
121 |
122 | .arrow-right {
123 | display: inline-block;
124 | overflow: hidden;
125 | position: relative;
126 | height: 16px;
127 | width: 8px;
128 | margin-left:15px;
129 | }
130 |
131 |
132 | .arrow-right:before {
133 | border: 8px solid transparent;
134 | content: ' ';
135 | display: block;
136 | position: absolute;
137 | z-index: 2;
138 | border-left-color: #4DAF52;
139 | left: 0;
140 | top: 2px;
141 | }
142 | [data-a11y-dialog-native] .dialog-overlay {
143 | display: none
144 | }
145 |
146 | dialog[open] {
147 | display: block
148 | }
149 |
150 | .dialog[aria-hidden="true"] {
151 | display: none
152 | }
153 |
154 | dialog::backdrop {
155 | background-color: rgba(0,0,0,0.66)
156 | }
157 |
158 | .dialog-content {
159 | background-color: #fff;
160 | z-index: 3;
161 | position: fixed;
162 | top: 50%;
163 | left: 50%;
164 | -webkit-transform: translate(-50%,-50%);
165 | -ms-transform: translate(-50%,-50%);
166 | transform: translate(-50%,-50%);
167 | margin: 0;
168 | max-height:90%;
169 | overflow-y: scroll;
170 | }
171 |
172 | @keyframes fade-in {
173 | from {
174 | opacity: 0
175 | }
176 |
177 | to {
178 | opacity: 1
179 | }
180 | }
181 |
182 | @keyframes appear {
183 | from {
184 | transform: translate(-50%,-40%);
185 | opacity: 0
186 | }
187 |
188 | to {
189 | transform: translate(-50%,-50%);
190 | opacity: 1
191 | }
192 | }
193 |
194 | .dialog:not([aria-hidden='true']) > .dialog-overlay {
195 | animation: fade-in 200ms 1 both
196 | }
197 |
198 | .dialog:not([aria-hidden='true']) > .dialog-content {
199 | animation: appear 400ms 150ms 1 both
200 | }
201 |
202 | .dialog-content {
203 | padding: 1em;
204 | max-width: 90%;
205 | width: 600px;
206 | border-radius: 2px
207 | }
208 |
209 | .dialog-container {
210 | padding: 20px
211 | }
212 |
213 | .dialog h1, .dialog .title {
214 | display: block;
215 | font-weight: 900;
216 | text-align: center;
217 | margin: 0;
218 | font-size: 2.25em;
219 | font-family: 'ESPI Slab',sans-serif;
220 | line-height: 1.1;
221 | color: #616161
222 | }
223 |
224 | .dialog-close {
225 | position: absolute;
226 | top: .5em;
227 | right: .5em;
228 | border: 0;
229 | padding: 0;
230 | background-color: transparent;
231 | font-weight: 700;
232 | font-size: 1.25em;
233 | width: 1.2em;
234 | height: 1.2em;
235 | text-align: center;
236 | cursor: pointer;
237 | transition: .15s
238 | }
239 |
240 | @media screen and (min-width: 700px) {
241 | .dialog-close {
242 | top: 1em;
243 | right: 1em
244 | }
245 | }
246 | .dialog-content {
247 | width: 90%;
248 | }
249 | .dialog-content-small {
250 | max-width: 500px;
251 | }
252 |
253 | .dialog-container {
254 | max-width: 99%;
255 | overflow-x: scroll;
256 | }
257 |
258 |
--------------------------------------------------------------------------------
/Web-GUI-for-SQLite.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Web GUI for SQLite
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Web GUI for SQLite
15 |
16 |
17 |
94 |
95 |
96 |
Your database
97 |
98 |
99 |
Table
100 |
No table
101 |
102 |
View
103 |
No view
104 |
105 |
106 |
107 |
108 |
109 |
158 |
159 |
160 |
161 |
162 |
163 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | ×
182 |
183 | Informations
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 | ×
194 |
195 |
196 |
228 |
229 |
230 |
231 |
238 |
239 |
--------------------------------------------------------------------------------
/Web-GUI-for-SQLite.js:
--------------------------------------------------------------------------------
1 | const Structure = Object.freeze({
2 | TABLE: "table",
3 | VIEW: "view",
4 | INDEX: "index",
5 | SEQUENCE: "sequence"
6 | });
7 | var ReadModeEnum = {
8 | TEXT: 1,
9 | ARRAY_BUFFER: 2,
10 | DATA_URL: 3
11 | };
12 | class SQLiteWebJS {
13 | constructor() {
14 | this.dialogTable = null;
15 | this.dialogData = null;
16 | this.db = null;
17 | this.messages = null;
18 | this.myCodeMirror = null;
19 | this.currentStructure = null;
20 | this.currentQuery = null;
21 | }
22 | createDatabase () {
23 | this.db = new SQL.Database();
24 | }
25 | loadStream (stream) {
26 | this.db = new SQL.Database(new Uint8Array(stream));
27 | }
28 | execute (query, header) {
29 | if (!this.db) {
30 | this.createDatabase();
31 | }
32 | if (!header) {
33 | var rows = [];
34 | try {
35 | this.db.each(query, {}, function(row){ rows.push(row); });
36 | }
37 | catch (e) {
38 | return new Error(e.message);
39 | }
40 | return rows;
41 | } else {
42 | var result = null;
43 | var resultObject = {columns: []};
44 | try {
45 | result = this.db.exec(query);
46 | }
47 | catch (e) {
48 | return new Error(e.message);
49 | }
50 | resultObject.rows = [];
51 | if (result.length) {
52 | resultObject.columns = result[0].columns;
53 | if (result[0].values) {
54 | result[0].values.forEach(function (value) {
55 | var row = {};
56 | resultObject.columns.forEach(function (column, index) {
57 | row[column] = value[index];
58 | });
59 | resultObject.rows.push(row);
60 | });
61 | }
62 | }
63 | return resultObject;
64 | }
65 | }
66 | tables () {
67 | if (!this.db) {
68 | this.createDatabase();
69 | }
70 | var tables = [];
71 | this.db.each("SELECT name, sql FROM sqlite_master WHERE type='table' ", {}, function(row){ tables.push(row); });
72 | return tables;
73 | }
74 | setMessage(type, message) {
75 | while (this.message.classList.length > 0) {
76 | this.message.classList.remove(this.message.classList.item(0));
77 | }
78 | this.message.classList.add(type);
79 | this.message.innerText = message;
80 | this.message.style.display = '';
81 | }
82 | resetMessage() {
83 | while (this.message.classList.length > 0) {
84 | this.message.classList.remove(this.message.classList.item(0));
85 | }
86 | this.message.innerText = '';
87 | this.message.style.display = 'none';
88 | }
89 | openSQLite() {
90 | document.getElementById('file-input').click();
91 | }
92 | selectCSVFile() {
93 | document.getElementById('csv-file-input').click();
94 | }
95 | exportFile(fileObject) {
96 | var blob = (fileObject.blob ? fileObject.blob : new Blob([fileObject.data], { type: fileObject.mime }));
97 | if (navigator.msSaveBlob) { // IE 10+
98 | navigator.msSaveBlob(blob, fileObject.filename);
99 | } else {
100 | var link = document.createElement("a");
101 | if (link.download !== undefined) { // feature detection
102 | // Browsers that support HTML5 download attribute
103 | var url = URL.createObjectURL(blob);
104 | link.setAttribute("href", url);
105 | link.setAttribute("download", fileObject.filename);
106 | link.style.visibility = 'hidden';
107 | document.body.appendChild(link);
108 | link.click();
109 | document.body.removeChild(link);
110 | }
111 | }
112 | }
113 | exportDatabaseFile() {
114 | if (!this.db) {
115 | this.createDatabase();
116 | }
117 | var uint8Array = this.db.export();
118 | var fileInput = document.getElementById('file-input').value;
119 | var filename = function(fullPath) {
120 | var filename = '';
121 | if (fullPath) {
122 | var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
123 | filename = fullPath.substring(startIndex);
124 | if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
125 | filename = filename.substring(1);
126 | }
127 | }
128 | return filename;
129 | }
130 | this.exportFile({data: uint8Array, filename: fileInput ? filename(fileInput) : "file.sqli", mime: 'application/octet-stream'});
131 | }
132 | getColumns(tableName) {
133 | var rows = this.execute("PRAGMA table_info(" + tableName + ")");
134 | if (rows instanceof Error) {
135 | return null;
136 | }
137 | return rows;
138 | }
139 | getTableInfo(tableName) {
140 | var tableData = {type: Structure.TABLE, name: tableName, columns: this.getColumns(tableName), pk: null, query: null, orderBy: null, result: null};
141 | tableData.pk = tableData.columns.reduce(function(conso, row) { if (row.pk > 0) { conso.push(row.name); } return conso; }, []);
142 | if (tableData.pk.length === 0) { // use rowid to delete row ...
143 | tableData.query = "select rowid, * from "+ tableName;
144 | } else {
145 | tableData.query = "select * from "+ tableName;
146 | }
147 | return tableData;
148 | }
149 | getViewInfo(viewName) {
150 | var viewData = {type: Structure.VIEW, name: viewName, columns: this.getColumns(viewName), query: "select * from "+ viewName, orderBy: null, result: null};
151 | return viewData;
152 | }
153 | showToTableContainer(container) {
154 | this.dialogTable.hide();
155 | document.getElementById("table-name").innerHTML = (this.currentStructure.type == Structure.VIEW ? "View " : "Table ") +this.currentStructure.name;
156 | while(document.getElementById("container-table").firstChild) {
157 | document.getElementById("container-table").removeChild(document.getElementById("container-table").firstChild);
158 | }
159 | document.getElementById("container-table").appendChild(container);
160 |
161 | document.getElementById("menu-sqlite-insert").style.display = (this.currentStructure.type == Structure.VIEW ? 'none' : '');
162 | document.getElementById("menu-sqlite-importCSV").style.display = (this.currentStructure.type == Structure.VIEW ? 'none' : '');
163 |
164 | this.dialogTable.show();
165 | }
166 | exportResult(type) {
167 | switch (type) {
168 | case 'csv':
169 | default:
170 | if (!this.currentQuery) {
171 | alert('You must execute a query before you can export!');
172 | return;
173 | }
174 | this.exportFile({data: this.getExportData(this.currentQuery), filename: "file.csv", mime: 'text/csv'});
175 | break;
176 | }
177 | }
178 | exportTable(type) {
179 | switch (type) {
180 | case 'csv':
181 | default:
182 | this.exportFile({data: this.getExportData(this.currentStructure), filename: "file.csv", mime: 'text/csv'});
183 | break;
184 | }
185 | }
186 | loadTable(tableName) {
187 | // this.manageMenu('table', tableName);
188 | this.currentStructure = this.getTableInfo(tableName);
189 | var result = this.executeQuery(this.currentStructure);
190 | // this.selectTab ('row');
191 | // this.insertView(this.currentStructure);
192 | this.structureView(tableName, this.currentStructure.type);
193 | if (result && result.message) {
194 | this.showToTableContainer(result.containerObj);
195 | }
196 | }
197 | loadView(viewName) {
198 | // this.manageMenu('view');
199 | // this.selectTab ('row');
200 | this.currentStructure = this.getViewInfo(viewName);
201 | var result = this.executeQuery(this.currentStructure);
202 | this.structureView(viewName, this.currentStructure.type);
203 | if (result && result.message) {
204 | this.showToTableContainer(result.containerObj);
205 | }
206 | }
207 | loadDatabase(all) {
208 | var self = this;
209 | var tableList = document.getElementById('table-list');
210 | this.load('table', "SELECT tbl_name as name FROM sqlite_master WHERE type='table' Order by tbl_name ASC",
211 | function(row) {
212 | self.loadTable(row.name);
213 | }
214 | );
215 | if (tableList.style.display == 'none') {
216 | if (document.getElementById('tablePlus')) document.getElementById('tablePlus').click();
217 | }
218 | this.load('view', "SELECT name as name, sql as sql_structure FROM sqlite_master WHERE type='view' Order by name ASC",
219 | function(row) {
220 | self.loadView(row.name);
221 | }
222 | );
223 | }
224 | format(sql) {
225 | return sql.replace(new RegExp(',([^0-9])', 'g'), ",\n $1");
226 | }
227 | structureView(tableName, type) {
228 | if (!type) {
229 | type = Structure.TABLE;
230 | }
231 | var container = document.createElement('div');
232 | container.classList.add('SQLite-WebJS-structure');
233 | while (container.firstChild) container.removeChild(container.firstChild);
234 | var containerSQL = document.createElement('div');
235 | container.appendChild(containerSQL);
236 | // containerSQL.classList.add('container-action');
237 | var pre = document.createElement('pre');
238 | containerSQL.appendChild(pre);
239 |
240 | var sql = this.execute("SELECT sql as sql_structure FROM sqlite_master WHERE type='" + (type == Structure.TABLE ? 'table' : 'view') + "' and tbl_name = '" + tableName + "' ", true);
241 | if (sql && sql.rows && sql.rows.length) {
242 | pre.appendChild(document.createTextNode(this.format(sql.rows[0].sql_structure + ';')));
243 | }
244 |
245 | var indexes = this.execute("select sql as index_sql from sqlite_master where type = 'index' and tbl_name = '" + tableName + "' and name not like 'sqlite_autoindex_%' and sql is not null", true);
246 | if (indexes && indexes.rows && indexes.rows.length) {
247 | var self = this;
248 | indexes.rows.forEach(function (index) {
249 | pre.appendChild(document.createTextNode("\n" + self.format(index.index_sql + ';')));
250 | });
251 | }
252 | return container;
253 | }
254 | load(type, query, callback) {
255 | var container = document.getElementById(type + '-list');
256 | while(container.firstChild){
257 | container.removeChild(container.firstChild);
258 | }
259 | var rows = this.execute(query);
260 | if (rows instanceof Error) {
261 | container.innerHTML = 'An error has occured';
262 | return;
263 | }
264 | if (rows.length === 0) {
265 | container.innerHTML = "No " + type;
266 | return;
267 | }
268 | rows.forEach(function(row) {
269 | var element = document.createElement("div");
270 | element.appendChild(document.createTextNode(row.name));
271 | if (callback) {
272 | (function(r) {
273 | var todraw = r;
274 | element.addEventListener('click', function() {
275 | callback(todraw);
276 | }, false);
277 | }(row));
278 | element.classList.add('SQLite-WebJS-browser-canbeclick');
279 | element.setAttribute('data-name', 'menu-' + type + '-' + row.name);
280 | }
281 | container.appendChild(element);
282 | });
283 | }
284 | getWhereFromPKForCurrentTable(row) {
285 | var self = this;
286 | if (this.currentStructure.pk.length) {
287 | return this.currentStructure.pk.reduce(function(consolidation, key) {
288 | return (consolidation == '' ? '' : consolidation + " and ")
289 | + key + " = " + self.valueForUpsert(self.getColumnFromCurrentTable(key), row[key], false) + ' ';
290 | }, '');
291 | }
292 | return ' rowid = ' + row.rowid;
293 | }
294 | getColumnFromCurrentTable(field) {
295 | return this.currentStructure.columns.reduce(function(accumulator, currentValue) { if (currentValue.name == field) return currentValue; else return accumulator; }, null);
296 | }
297 | executeQuery(options, containerObj = null) {
298 | var self = this;
299 | var resultExecute = {message: null, containerObj : containerObj};
300 | var exportToCSVContainer = document.getElementById((options.type ? 'exportToCSVRowContainer' : 'exportToCSVContainer'));
301 | options.result = this.execute(options.query + (options && options.orderBy ? options.orderBy : ''), true);
302 | if (!resultExecute.containerObj) {
303 | resultExecute.containerObj = document.createElement('div');
304 | }
305 | let table = resultExecute.containerObj.querySelector('table');
306 | if (!table) {
307 | if (options && [Structure.TABLE, Structure.VIEW].indexOf(options.type) !== -1) {
308 | // var containerRow = document.getElementById('container-row');
309 | // while (containerRow.firstChild) containerRow.removeChild(containerRow.firstChild);
310 | // table = document.getElementById('row-results');
311 | table = document.createElement('table');
312 | table.id = 'row-results';
313 | table.classList.add("SQLite-WebJS-results");
314 | table.createTHead();
315 | table.createTBody();
316 |
317 | const info = document.createElement('div');
318 | info.classList.add('SQLite-WebJS-editor-valid');
319 | info.id = 'table-message';
320 | info.innerText = '';
321 | resultExecute.containerObj.appendChild(info);
322 | resultExecute.containerObj.appendChild(table);
323 | } else {
324 | table = document.getElementById('results');
325 | }
326 | }
327 | var tBody = table.getElementsByTagName('tbody')[0];
328 | var tHeader = table.getElementsByTagName('thead')[0];
329 | var rowCount = table.rows.length;
330 | for (var i = rowCount - 1; i >= 0; i--) {
331 | table.deleteRow(i);
332 | }
333 |
334 | if (exportToCSVContainer) exportToCSVContainer.style.display = 'none';
335 |
336 | if (options.result instanceof Error) {
337 | throw options.result;
338 | }
339 |
340 | var iLine = 0;
341 | var iColumn = 0;
342 | var iCSV = 0;
343 | var newHeader = tHeader.insertRow(tHeader.rows.length);
344 | options.result.columns.forEach(function(field, index) {
345 | if (index === 0 && options && options.type == Structure.TABLE) {
346 | newHeader.insertCell(iColumn).appendChild(document.createTextNode('Actions'));
347 | iColumn++;
348 | if (!options.pk.length) {
349 | return;
350 | }
351 | }
352 | var cell = newHeader.insertCell(iColumn);
353 | iCSV++;
354 | cell.appendChild(document.createTextNode(field));
355 | if (options && [Structure.TABLE, Structure.VIEW].indexOf(options.type) !== -1) {
356 | var ascButton = document.createElement('span');
357 | ascButton.innerHTML = "▲";
358 | // ascButton.type = 'button';
359 | ascButton.classList.add('SQLite-WebJS-browser-order');
360 | ascButton.onclick = function() {
361 | self.currentStructure.orderBy = ' ORDER BY ' + field + ' ASC ' ;
362 | self.executeQuery(self.currentStructure, resultExecute.containerObj);
363 | };
364 | cell.appendChild(document.createTextNode(" "));
365 | cell.appendChild(ascButton);
366 | cell.appendChild(document.createTextNode(" "));
367 | var descButton = document.createElement('span');
368 | descButton.innerHTML = "▼";
369 | descButton.classList.add('SQLite-WebJS-browser-order');
370 | // descButton.type = 'button';
371 | descButton.onclick = function() {
372 | self.currentStructure.orderBy = ' ORDER BY ' + field + ' DESC ' ;
373 | self.executeQuery(self.currentStructure, resultExecute.containerObj);
374 | };
375 | cell.appendChild(descButton);
376 | }
377 |
378 | iColumn++;
379 | });
380 |
381 | if (options.result.rows.length) {
382 | if (exportToCSVContainer) exportToCSVContainer.style.display = '';
383 | if (options.result.rows.length == 1) resultExecute.message = "1 row";
384 | else resultExecute.message = options.result.rows.length + " rows";
385 | }
386 | else {
387 | resultExecute.message = "Query has no result";
388 | }
389 | if (options && options.type == Structure.TABLE) {
390 | const info = resultExecute.containerObj.querySelector('#table-message');
391 | info.innerText = resultExecute.message;
392 | }
393 | options.result.rows.forEach(function (row) {
394 | iLine++;
395 | var newRow = tBody.insertRow(tBody.rows.length);
396 | if (iLine % 2 === 1) {
397 | newRow.className = "SQLite-WebJS-results-odd";
398 | }
399 | iColumn = 0;
400 | iCSV = 0;
401 | options.result.columns.forEach(function (field, index) {
402 | if (options && options.type == Structure.TABLE && index === 0) {
403 | // Delete
404 | var img = document.createElement('img');
405 | img.setAttribute('data-name', 'deleteRowButton');
406 | img.src = './image/error.png';
407 | img.classList.add('SQLite-WebJS-browser-img-click');
408 | img.onclick = function () {
409 | self.execute("Delete from " + options.name
410 | + " Where "
411 | + self.getWhereFromPKForCurrentTable(row)
412 | );
413 | self.executeQuery(options, resultExecute.containerObj);
414 | alert('The row has been removed');
415 | };
416 | newRow.insertCell(iColumn).appendChild(img);
417 | iColumn++;
418 | if (!options.pk.length) {
419 | return;
420 | }
421 | }
422 | var cellData = newRow.insertCell(iColumn);
423 | var dataSpan = document.createElement('span');
424 | dataSpan.appendChild(document.createTextNode((row[field] === null ? '' : row[field])));
425 | cellData.appendChild(dataSpan);
426 | if (options && options.type == Structure.TABLE) {
427 | var column = self.getColumnFromCurrentTable(field);
428 | var editInput = document.createElement('input');
429 | editInput.type = "text";
430 | editInput.value = (row[field] === null ? '' : row[field]);
431 | editInput.style.display = 'none';
432 | cellData.appendChild(editInput);
433 | cellData.ondblclick = function() {
434 | dataSpan.style.display = 'none';
435 | editInput.style.display = '';
436 | editInput.focus();
437 | // todo: qd perte focus ... edit
438 | editInput.onblur = function() {
439 | editInput.style.display = 'none';
440 | dataSpan.style.display = '';
441 | var res = self.execute("Update " + options.name
442 | + " set " + field + " = " + self.valueForUpsert(column, editInput.value, editInput.value == '')
443 | + " Where " + self.getWhereFromPKForCurrentTable(row) );
444 | if (res instanceof Error) {
445 | alert("An error has occured: " + (res.message ? res.message : ''));
446 | return;
447 | } else {
448 | row[field] = (editInput.value == '' ? null : editInput.value);
449 | while(dataSpan.firstChild) dataSpan.removeChild(dataSpan.firstChild);
450 | dataSpan.appendChild(document.createTextNode((row[field] === null ? '' : row[field])));
451 | }
452 |
453 | };
454 | };
455 | }
456 | iCSV++;
457 | iColumn++;
458 | });
459 | });
460 | return resultExecute;
461 | }
462 | insertView(tableInfo) {
463 | const self = this;
464 | const container = document.createElement('div');
465 | container.id = "container-insert";
466 | container.classList.add('SQLite-WebJS-container-center');
467 | const table = document.createElement('table');
468 | container.appendChild(table);
469 | table.id="row-insert";
470 | table.classList.add('SQLite-WebJS-results');
471 | const tHeader = table.createTHead();
472 | tHeader.appendChild(document.createElement('tr'));
473 | ['Column', 'Type', 'Null', 'Value'].forEach(function (c) {
474 | const th = document.createElement('th');
475 | th.appendChild(document.createTextNode(c));
476 | tHeader.firstChild.appendChild(th);
477 | });
478 | const tBody = table.createTBody();
479 | const tfoot = table.createTFoot();
480 | const th = document.createElement('th');
481 | th.colSpan = "4";
482 | tfoot.appendChild(th);
483 | const containerFoot = document.createElement('div');
484 | th.appendChild(containerFoot);
485 | containerFoot.classList.add('SQLite-WebJS-container-center');
486 | const input = document.createElement('input');
487 | containerFoot.appendChild(input);
488 | input.type = "button";
489 | input.classList.add("SQLite-WebJS-button");
490 | input.value="Insert";
491 | input.id="insertElementToTable";
492 | input.addEventListener('click', function(e) {
493 | self.insertElementToTable();
494 | }, false);
495 |
496 | var rowCount = table.rows.length;
497 | for (var i = rowCount - 2; i > 0; i--) {
498 | table.deleteRow(i);
499 | }
500 | tableInfo.columns.forEach(function (column, index) {
501 | var newRow = tBody.insertRow(tBody.rows.length);
502 | if (index % 2 === 1) {
503 | newRow.className = "SQLite-WebJS-results-odd";
504 | }
505 | newRow.insertCell(0).appendChild(document.createTextNode(column.name));
506 |
507 | newRow.insertCell(1).appendChild(document.createTextNode(column.type));
508 |
509 | if (tableInfo.pk.indexOf(column.name) === -1) {
510 | var checkboxNull = document.createElement('input');
511 | checkboxNull.type = "checkbox";
512 | checkboxNull.value = "null";
513 | checkboxNull.name = column.name + "_NULL";
514 | newRow.insertCell(2).appendChild(checkboxNull);
515 | } else {
516 | newRow.insertCell(2);
517 | }
518 | if (column.type == 'boolean') {
519 | var selectAdd = document.createElement('select');
520 | selectAdd.name = column.name;
521 | var option=document.createElement("option");
522 | option.text="true";
523 | option.value="true";
524 | selectAdd.add(option, null);
525 | var option=document.createElement("option");
526 | option.text="false";
527 | option.value="false";
528 | selectAdd.add(option, null);
529 | newRow.insertCell(3).appendChild(selectAdd);
530 | } else {
531 | var inputAdd = document.createElement('input');
532 | inputAdd.type = "text";
533 | inputAdd.value = "";
534 | inputAdd.name = column.name;
535 | var cell = newRow.insertCell(3);
536 | cell.appendChild(inputAdd);
537 | if (column.type == 'blob') {
538 | cell.appendChild(document.createTextNode(' (hex literal)'));
539 | }
540 | }
541 | });
542 | return container;
543 | }
544 | insertElementToTable() {
545 | var self = this;
546 | var values = '';
547 | if (!this.currentStructure.columns.some(function (column) {
548 | var isNull = document.querySelector('#row-insert input[type="checkbox"][name="' + column.name + '_NULL"]');
549 | var input = document.querySelector('#row-insert input[name="' + column.name + '"]');
550 | var select = document.querySelector('#row-insert select[name="' + column.name + '"]');
551 | if (values !== '') {
552 | values += ", ";
553 | }
554 | values += self.valueForUpsert(column, (select ? select[select.selectedIndex].value : input.value), isNull && isNull.checked);
555 | return false;
556 | })) {
557 | var result = this.execute("Insert into "+ this.currentStructure.name + " VALUES (" + values + ") ");
558 | if (result instanceof Error) {
559 | alert('An error has occured: ' + result.message);
560 | } else {
561 | alert('Your row has been inserted');
562 | this.loadTable(this.currentStructure.name);
563 | }
564 | }
565 | }
566 | valueForUpsert(column, value, isNull) {
567 | if (isNull) {
568 | return " null";
569 | } else if (column.type.toLowerCase() == 'boolean') {
570 | return value;
571 | } else if (column.type.toLowerCase().indexOf('char') !== -1 || column.type.toLowerCase() == 'text' || column.type.toLowerCase() == 'clob'
572 | || column.type.toLowerCase() == 'datetime' || column.type.toLowerCase() == 'date' ) {
573 | // CHARACTER(20) VARCHAR(255) VARYING CHARACTER(255) NCHAR(55) NATIVE CHARACTER(70) NVARCHAR(100) TEXT CLOB
574 | return " '" + value.replace("'", "''") + "'";
575 | } else if (column.type.toLowerCase() == 'blob') {
576 | return " X'" + value.replace("'", "''") + "'";
577 | } else if (value == '' && (column.type.toLowerCase().indexOf('int') !== -1 || ['real', 'double', 'double precision', 'float'].indexOf(column.type.toLowerCase()) !== -1
578 | || column.type.toLowerCase() == 'numeric' || column.type.toLowerCase().indexOf('numeric') !== -1 || column.type.toLowerCase().indexOf('decimal') !== -1 )) {
579 | return " null";
580 | }
581 | return value;
582 | }
583 | loadCSVData(data) {
584 | var self = this;
585 | var lineArray = data.match(/[^\r\n]+/g);
586 | var delimiter = document.getElementById('ImportSeparator').value;
587 | var nullString = document.getElementById('ImportNullString').value;
588 | var header = document.getElementById('ImportHeader').value;
589 | var errors = '';
590 | var nbRowsInserted = 0;
591 | var nbRowsRejected = 0;
592 | var columnsToImport = null;
593 | if (header === 'yes') {
594 | columnsToImport = [];
595 | if (lineArray.length === 0) {
596 | this.resetMessage();
597 | this.setMessage('SQLite-WebJS-editor-error', "Empty file");
598 | return;
599 | }
600 | var errorColumnUnknown = false;
601 | lineArray[0].split(delimiter).forEach(function (columnName) {
602 | var c = self.currentStructure.columns.reduce(function(accumulator, currentValue) { if (currentValue.name == columnName) return currentValue; else return accumulator; }, null);
603 | if (c === null) {
604 | self.resetMessage();
605 | self.setMessage('SQLite-WebJS-editor-error', "Unknown " + columnName + " column");
606 | errorColumnUnknown = true;
607 | return;
608 | }
609 | columnsToImport.push(c);
610 | });
611 | if (errorColumnUnknown) {
612 | return;
613 | }
614 | } else {
615 | columnsToImport = self.currentStructure.columns;
616 | }
617 | // begin run
618 | lineArray.forEach(function (line, lineIndex) {
619 | if (header === 'yes' && lineIndex == 0) {
620 | return;
621 | }
622 | var columns = '';
623 | var values = '';
624 | var columnArray = line.split(delimiter);
625 | columnsToImport.forEach(function (column, index) {
626 | if (columns !== '') columns += ', ';
627 | columns += column.name;
628 | if (values !== '') values += ', ';
629 | values += self.valueForUpsert(column, columnArray[index], index >= columnArray.length || columnArray[index] === nullString);
630 | });
631 | var result = self.execute("insert into " + self.currentStructure.name + " (" + columns + ") values (" + values + ")", true);
632 | if (result instanceof Error) {
633 | nbRowsRejected++;
634 | errors += result.message + "\n";
635 | } else {
636 | nbRowsInserted++;
637 | }
638 | });
639 | // commit
640 | if (nbRowsInserted > 0) {
641 | this.loadTable(self.currentStructure.name);
642 | }
643 | this.resetMessage();
644 | if (nbRowsRejected == 0) {
645 | this.setMessage('SQLite-WebJS-editor-valid', nbRowsInserted + " rows inserted.");
646 | } else {
647 | this.setMessage('SQLite-WebJS-editor-error', nbRowsRejected + " rows rejected (" + nbRowsInserted + " rows inserted). Details:\n" + errors);
648 | }
649 | }
650 | getExportData(structure) {
651 | var exportCSV = '';
652 | var header = document.getElementById('header' + (structure.type ? 'Row' : 'Query')).value;
653 | var nullString = document.getElementById('nullString' + (structure.type ? 'Row' : '')).value;
654 | var separator = document.getElementById('separator' + (structure.type ? 'Row' : '')).value;
655 | if (structure.result) {
656 | if (header !== 'no') {
657 | exportCSV += structure.result.columns.reduce(function(conso, columnName, index) {
658 | if (index == 0 && structure.type && structure.type == Structure.TABLE) {
659 | if (!structure.pk.length) {
660 | // rowid: not to export...
661 | return null;
662 | }
663 | }
664 | return (conso == null ? '' : conso + separator) + columnName;
665 | }, null);
666 | exportCSV += "\n";
667 | }
668 | structure.result.rows.forEach(function (row) {
669 | var iCSV = 0;
670 | Object.keys(row).forEach(function (field, index) {
671 | if (structure.type && structure.type == Structure.TABLE && index === 0) {
672 | if (!structure.pk.length) {
673 | return;
674 | }
675 | }
676 | exportCSV += (iCSV > 0 ? separator : '') + (row[field] === null ? nullString : row[field]);
677 | iCSV++;
678 | });
679 | exportCSV += "\n";
680 | });
681 | }
682 | return exportCSV;
683 | }
684 | reverseDisplay (divId) {
685 | var div = (typeof divId === 'string' ? document.getElementById(divId) : divId);
686 | if (div) {
687 | if (div.style.display == 'none') {
688 | div.style.display = '';
689 | } else {
690 | div.style.display = 'none';
691 | }
692 | }
693 | }
694 | readSingleFile (e, readAs, callback) {
695 | var files;
696 | if (e.target && e.target.files) {
697 | files = e.target.files;
698 | } else if (e.dataTransfer && e.dataTransfer.files)
699 | {
700 | files = e.dataTransfer.files;
701 | }
702 | if (!files || files.length == 0) {
703 | callback(null);
704 | return;
705 | }
706 | Array.prototype.forEach.call(files, function(file) {
707 | var reader = new FileReader();
708 | reader.onload = function() {
709 | callback(reader.result, {file: file});
710 | };
711 | if (readAs === ReadModeEnum.ARRAY_BUFFER) reader.readAsArrayBuffer(file);
712 | else if (readAs === ReadModeEnum.DATA_URL) reader.readAsDataURL(file);
713 | else reader.readAsText(file);
714 | });
715 | }
716 | init() {
717 | var self = this;
718 | this.message = document.getElementById('editor-message');
719 | this.myCodeMirror = CodeMirror.fromTextArea(document.getElementById('editor-container'), { lineNumbers: true, viewportMargin: Infinity });
720 | this.myCodeMirror.setSize(null, 250);
721 | ['table', /*'index', 'sequence', */'view'].forEach(function (structure) {
722 | var structureTitle = document.getElementById(structure);
723 | var imgPlus = document.createElement('img');
724 | var imgMinus = document.createElement('img');
725 | var fDisplay = function () {
726 | self.reverseDisplay(structure + '-list');
727 | self.reverseDisplay(imgMinus.id);
728 | self.reverseDisplay(imgPlus.id);
729 | };
730 | imgPlus.id = structure + 'Plus';
731 | imgPlus.src = './image/plus.png';
732 | imgPlus.classList.add('SQLite-WebJS-browser-img-click');
733 | structureTitle.parentNode.insertBefore(imgPlus, structureTitle);
734 | imgPlus.onclick = fDisplay;
735 | imgMinus.id = structure + 'Minus';
736 | imgMinus.src = './image/minus.png';
737 | imgMinus.classList.add('SQLite-WebJS-browser-img-click');
738 | imgMinus.style.display = 'none';
739 | structureTitle.parentNode.insertBefore(imgMinus, structureTitle);
740 | imgMinus.onclick = fDisplay;
741 | structureTitle.onclick = fDisplay;
742 | });
743 |
744 | document.getElementById('file-input').addEventListener('change', function(e) {
745 | self.resetMessage();
746 | if (document.getElementById('file-input').value != '') {
747 | self.setMessage('SQLite-WebJS-editor-inprogress', "Your database is loading.");
748 | setTimeout(function() {
749 | self.readSingleFile(e, ReadModeEnum.ARRAY_BUFFER, function(data) {
750 | document.getElementById('file-input').value = '';
751 | self.loadStream(data);
752 | self.loadDatabase(true);
753 | self.resetMessage();
754 | self.setMessage('SQLite-WebJS-editor-valid', "Your database has been loaded.");
755 | });
756 | }, 1);
757 | }
758 | }, false);
759 |
760 | document.getElementById('csv-file-input').addEventListener('change', function(e) {
761 | self.resetMessage();
762 | if (document.getElementById('csv-file-input').value != '') {
763 | self.setMessage('SQLite-WebJS-editor-inprogress', "Your CSV file is loading.");
764 | setTimeout(function() {
765 | self.readSingleFile(e, ReadModeEnum.TEXT, function(data) {
766 | document.getElementById('csv-file-input').value = '';
767 | self.loadCSVData(data);
768 | });
769 | }, 1);
770 | }
771 | }, false);
772 |
773 | document.getElementById('update').addEventListener('click', function(e) {
774 | self.resetMessage();
775 | self.setMessage('SQLite-WebJS-editor-inprogress', "Your database is loading.");
776 | setTimeout(function() {
777 | self.loadDatabase(false);
778 | self.resetMessage();
779 | self.setMessage('SQLite-WebJS-editor-valid', "Table, view, index and sequence lists have been updated.");
780 | setTimeout(function () {
781 | self.resetMessage(['SQLite-WebJS-editor-valid']);
782 | }, 1000);
783 | }, 1);
784 | }, false);
785 |
786 | document.getElementById('ExecuteQuery').addEventListener('click', function(e) {
787 | var selection = self.myCodeMirror.getSelection();
788 | self.currentQuery = {
789 | query: (selection != '' && selection != null ? selection : self.myCodeMirror.getValue("\n")),
790 | result : null
791 | };
792 | try {
793 | var result = self.executeQuery(self.currentQuery);
794 | if (result && result.message) {
795 | self.setMessage('SQLite-WebJS-editor-valid', result.message);
796 | }
797 | }
798 | catch (e) {
799 | self.setMessage('SQLite-WebJS-editor-error', e.message);
800 | }
801 | }, false);
802 |
803 | this.dialogData = new A11yDialog(document.getElementById('dialog-data'));
804 | this.dialogTable = new A11yDialog(document.getElementById('dialog-table'));
805 |
806 | this.initMenu();
807 | }
808 | closeMenu(exceptMenu = null) {
809 | document.querySelectorAll('.sub-menu ul').forEach(function(ul) {
810 | if (!exceptMenu || exceptMenu !== ul.parentNode) {
811 | ul.style.display = 'none';
812 | ul.parentNode.querySelectorAll("i.arrow").forEach(function(i) {
813 | i.classList.remove("up");
814 | i.classList.add("down");
815 | });
816 | }
817 | });
818 | }
819 | initMenu() {
820 | const self = this;
821 | this.closeMenu();
822 | document.querySelectorAll('.sub-menu a').forEach(function(a) {
823 | a.onclick = function () {
824 | let parent = a.parentNode;
825 | while (parent && !parent.classList.contains("sub-menu")) {
826 | parent = parent.parentNode;
827 | }
828 | if (parent) {
829 | self.closeMenu(parent);
830 | parent.querySelectorAll("ul").forEach(function(ul) {
831 | if (ul.style.display == '') {
832 | ul.style.display = 'none';
833 | } else {
834 | ul.style.display = '';
835 | }
836 | });
837 | parent.querySelectorAll("i.arrow").forEach(function(i) {
838 | i.classList.toggle("up");
839 | i.classList.toggle("down");
840 | });
841 | }
842 | };
843 | });
844 |
845 | document.getElementById("menu-sqlite-exportCSVResults").addEventListener('click', function(e) {
846 | self.closeMenu();
847 | document.getElementById("dialog-data-title").innerHTML = 'Export results to CSV';
848 | document.getElementById("dialog-data-container").innerHTML = `
849 | `;
889 | self.dialogData.show();
890 | });
891 | document.getElementById("menu-sqlite-openDB").addEventListener('click', function(e) {
892 | self.closeMenu();
893 | document.getElementById('file-input').click();
894 | });
895 | document.getElementById("menu-sqlite-saveDB").addEventListener('click', function(e) {
896 | self.closeMenu();
897 | self.exportDatabaseFile();
898 | });
899 |
900 | document.getElementById('menu-sqlite-exportCSV').addEventListener('click', function(e) {
901 | const container = document.createElement('div');
902 | container.innerHTML = ``;
939 | self.showToTableContainer(container);
940 | }, false);
941 | document.getElementById("menu-sqlite-importCSV").addEventListener('click', function(e) {
942 | self.closeMenu();
943 | const container = document.createElement('div');
944 | container.innerHTML = ``;
986 | self.showToTableContainer(container);
987 | });
988 | document.getElementById("menu-sqlite-insert").addEventListener('click', function(e) {
989 | self.closeMenu();
990 | const container = self.insertView(self.currentStructure);
991 | self.showToTableContainer(container);
992 | });
993 | document.getElementById("menu-sqlite-structure").addEventListener('click', function(e) {
994 | self.closeMenu();
995 | const container = self.structureView(self.currentStructure.name, self.currentStructure.type);
996 | self.showToTableContainer(container);
997 | });
998 | document.getElementById("menu-sqlite-browse").addEventListener('click', function(e) {
999 | self.closeMenu();
1000 | if (self.currentStructure.type === Structure.TABLE) {
1001 | self.loadTable(self.currentStructure.name);
1002 | } else if (self.currentStructure.type === Structure.VIEW) {
1003 | self.loadView(self.currentStructure.name);
1004 | }
1005 | });
1006 |
1007 | document.getElementById("menu-sqlite-openSQL").addEventListener('click', function(e) {
1008 | self.closeMenu();
1009 | document.getElementById('sql-input').click();
1010 | });
1011 | document.getElementById('sql-input').addEventListener('change', function(e) {
1012 | if (document.getElementById('sql-input').value != '') {
1013 | self.readSingleFile(e, ReadModeEnum.TEXT, function(data) {
1014 | document.getElementById('sql-input').value = '';
1015 | self.myCodeMirror.setValue(data);
1016 | });
1017 | }
1018 | });
1019 | document.getElementById("menu-sqlite-saveSQL").addEventListener('click', function(e) {
1020 | self.closeMenu();
1021 | self.exportFile({data: self.myCodeMirror.getValue("\n"), filename: "file.sql", mime: 'text/plain'});
1022 | });
1023 | }
1024 | }
--------------------------------------------------------------------------------
/external/a11y-dialog/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2017 Edenspiekermann
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/external/a11y-dialog/README.md:
--------------------------------------------------------------------------------
1 | # [A11y Dialog](http://edenspiekermann.github.io/a11y-dialog/)
2 |
3 | [a11y-dialog](http://edenspiekermann.github.io/a11y-dialog/) is a lightweight (1.3Kb) yet flexible script to create accessible dialog windows.
4 |
5 | ✔︎ No dependencies
6 | ✔︎ Leveraging the native `` element
7 | ✔︎ Closing dialog on overlay click and ESC
8 | ✔︎ Toggling `aria-*` attributes
9 | ✔︎ Trapping and restoring focus
10 | ✔︎ Firing events
11 | ✔︎ DOM and JS APIs
12 | ✔︎ Fast and tiny
13 |
14 | You can try the [live demo ↗](http://edenspiekermann.github.io/a11y-dialog/example/).
15 |
16 | ## Installation
17 |
18 | ```
19 | npm install a11y-dialog --save
20 | ```
21 |
22 | ## Usage
23 |
24 | You will find a concrete demo in the [example](https://github.com/edenspiekermann/a11y-dialog/tree/master/example) folder of this repository, but basically here is the gist:
25 |
26 | ### Expected DOM structure
27 |
28 | Here is the basic markup, which can be enhanced. Pay extra attention to the comments.
29 |
30 | ```html
31 |
35 |
36 |
39 |
40 |
41 |
47 |
48 |
49 |
54 |
55 |
56 |
63 |
64 |
70 |
71 | ×
72 |
73 |
74 |
79 | Dialog Title
80 |
81 |
84 |
85 |
86 | ```
87 |
88 | ### Styling layer
89 |
90 | The script itself does not take care of any styling whatsoever, not even the `display` property. It basically mostly toggles the `aria-hidden` attribute on the dialog itself and its counterpart containers.
91 |
92 | In browsers supporting the `` element, its visibility will be handled by the user-agent itself. Until support gets better across the board, the styling layer is up to the implementor (you).
93 |
94 | We recommend using at least the following styles to make everything work on both supporting and non-supporting user-agents:
95 |
96 | ```css
97 | /**
98 | * When the native `` element is supported, the overlay is implied and
99 | * can be styled with `::backdrop`, which means the DOM one should be removed.
100 | *
101 | * The `data-a11y-dialog-native` attribute is set by the script when the
102 | * `` element is properly supported.
103 | *
104 | * Feel free to replace `:first-child` with the overlay selector you prefer.
105 | */
106 | [data-a11y-dialog-native] > :first-child {
107 | display: none;
108 | }
109 |
110 | /**
111 | * When the `` element is not supported, its default display is `inline`
112 | * which can cause layout issues. This makes sure the dialog is correctly
113 | * displayed when open.
114 | */
115 | dialog[open] {
116 | display: block;
117 | }
118 |
119 | /**
120 | * When the native `` element is not supported, the script toggles the
121 | * `aria-hidden` attribute on the container. If `aria-hidden` is set to `true`,
122 | * the container should be hidden entirely.
123 | *
124 | * Feel free to replace `.dialog-container` with the container selector you
125 | * prefer.
126 | */
127 | .dialog-container[aria-hidden='true'] {
128 | display: none;
129 | }
130 | ```
131 |
132 | ### JavaScript instantiation
133 |
134 | ```javascript
135 | // Get the dialog element (with the accessor method you want)
136 | const el = document.getElementById('my-accessible-dialog');
137 |
138 | // Instantiate a new A11yDialog module
139 | const dialog = new A11yDialog(el);
140 | ```
141 |
142 | As recommended in the [HTML section](#expected-dom-structure) of this documentation, the dialog element is supposed to be on the same level as your content container(s). Therefore, the script will toggle the `aria-hidden` attribute of the siblings of the dialog element as a default. You can change this behaviour by passing a `NodeList`, an `Element` or a selector as second argument to the `A11yDialog` constructor:
143 |
144 | ```javascript
145 | const dialog = new A11yDialog(el, containers);
146 | ```
147 |
148 | ### Usage as a “modal”
149 |
150 | By default, a11y-dialog behaves as a dialog: it is closable with the ESC key, and by clicking the backdrop. However, it is possible to make it work like a “modal”, which would remove these features.
151 |
152 | To do so:
153 |
154 | 1. Add `role="alertdialog"` to the `` element or replace`role="dialog"` with `role="alertdialog"` in case you don’t use the `` element. This will make sure ESC doesn’t close the modal.
155 | 2. Remove `data-a11y-dialog-hide` from the overlay element. This makes sure it is not possible to close the modal by clicking outside of it.
156 | 3. In case the user actively needs to operate with the modal, you might consider removing the close button from it. Be sure to still offer a way to eventually close the modal.
157 |
158 | For more information about modals, refer to the [WAI ARIA recommendations](https://www.w3.org/TR/wai-aria-1.1/#alertdialog).
159 |
160 | ## DOM API
161 |
162 | The DOM API relies on `data-*` attributes. They all live under the `data-a11y-dialog-*` namespace for consistency, clarity and robustness. Two attributes are recognised:
163 |
164 | * `data-a11y-dialog-show`: the `id` of the dialog element is expected as a value
165 | * `data-a11y-dialog-hide`: the `id` of the dialog element is expected as a value; if omitted, the closest parent dialog element (if any) will be the target
166 |
167 | The following button will open the dialog with the `my-accessible-dialog` id when interacted with.
168 |
169 | ```html
170 | Open the dialog
171 | ```
172 |
173 | The following button will close the dialog in which it lives when interacted with.
174 |
175 | ```html
176 | ×
177 | ```
178 |
179 | The following button will close the dialog with the `my-accessible-dialog` id when interacted with. Given that the only focusable elements when the dialog is open are the focusable children of the dialog itself, it seems rather unlikely that you will ever need this but in case you do, well you can.
180 |
181 | ```html
182 | ×
183 | ```
184 |
185 | In addition, the library adds a `data-a11y-dialog-native` attribute (with no value) when the `` element is natively supported. This attribute is essentially used to customise the styling layer based on user-agent support (or lack thereof).
186 |
187 | ## JS API
188 |
189 | Regarding the JS API, it simply consists on `show()` and `hide()` methods on the dialog instance.
190 |
191 | ```javascript
192 | // Show the dialog
193 | dialog.show();
194 |
195 | // Hide the dialog
196 | dialog.hide();
197 | ```
198 |
199 | When the `` element is natively supported, the argument passed to `show()` and `hide()` is being passed to the native call to [`showModal()`](https://www.w3.org/TR/html52/interactive-elements.html#dom-htmldialogelement-showmodal) and [`close()`](https://www.w3.org/TR/html52/interactive-elements.html#dom-htmldialogelement-close). If necessary, the `returnValue` can be read using `dialog.dialog.returnValue`.
200 |
201 | For advanced usages, there are `create()` and `destroy()` methods. These are responsible for attaching click event listeners to dialog openers and closers. Note that the `create()` method is **automatically called on instantiation** so there is no need to call it again directly.
202 |
203 | ```javascript
204 | // Unbind click listeners from dialog openers and closers and remove all bound
205 | // custom event listeners registered with `.on()`
206 | dialog.destroy();
207 |
208 | // Bind click listeners to dialog openers and closers
209 | dialog.create();
210 | ```
211 |
212 | If necessary, the `create()` method also accepts the `targets` containers (the one toggled along with the dialog element) in the same form as the second argument from the constructor. If omitted, the one given to the constructor (or default) will be used.
213 |
214 | ## Events
215 |
216 | When shown, hidden and destroyed, the instance will emit certain events. It is possible to subscribe to these with the `on()` method which will receive the dialog DOM element and the [event object](https://developer.mozilla.org/en-US/docs/Web/API/Event) (if any).
217 |
218 | The event object can be used to know which trigger (opener / closer) has been used in case of a `show` or `hide` event.
219 |
220 | ```javascript
221 | dialog.on('show', function (dialogEl, event) {
222 | // Do something when dialog gets shown
223 | // Note: opener is `event.currentTarget`
224 | });
225 |
226 | dialog.on('hide', function (dialogEl, event) {
227 | // Do something when dialog gets hidden
228 | // Note: closer is `event.currentTarget`
229 | });
230 |
231 | dialog.on('destroy', function (dialogEl) {
232 | // Do something when dialog gets destroyed
233 | });
234 |
235 | dialog.on('create', function (dialogEl) {
236 | // Do something when dialog gets created
237 | // Note: because the initial `create()` call is made from the constructor, it
238 | // is not possible to react to this particular one (as registering will be
239 | // done after instantiation)
240 | });
241 | ```
242 |
243 | You can unregister these handlers with the `off()` method.
244 |
245 | ```javascript
246 | dialog.on('show', doSomething);
247 | // …
248 | dialog.off('show', doSomething);
249 | ```
250 |
251 |
252 | ## Nested dialogs
253 |
254 | Nested dialogs is a [questionable design pattern](https://ux.stackexchange.com/questions/52042/is-it-acceptable-to-open-a-modal-popup-on-top-of-another-modal-popup) that is not referenced anywhere in the [HTML 5.2 Dialog specification](https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element). Therefore it is discouraged and not supported by default by the library. That being said, if you still want to run with it, [Renato de Leão explains how in edenspiekermann/a11y-dialog#80](https://github.com/edenspiekermann/a11y-dialog/issues/80#issuecomment-377691629).
255 |
256 | ## Implementations
257 |
258 | If you happen to work with [React](https://github.com/facebook/react/) or [Vue](https://github.com/vuejs/vue) in your project, you’re lucky! There are already great light-weight wrapper implemented for a11y-dialog:
259 |
260 | - [React A11yDialog](https://github.com/HugoGiraudel/react-a11y-dialog)
261 | - [Vue A11yDialog](https://github.com/morkro/vue-a11y-dialog)
262 |
263 | ## Disclaimer & credits
264 |
265 | Originally, this repository was a fork from [accessible-modal-dialog ↗](https://github.com/gdkraus/accessible-modal-dialog) by Greg Kraus. It has gone through various stages since the initial implementation and both packages are no longer similar in the way they work.
266 |
--------------------------------------------------------------------------------
/external/a11y-dialog/a11y-dialog.js:
--------------------------------------------------------------------------------
1 | /* global NodeList, Element, Event, define */
2 |
3 | (function(global) {
4 | 'use strict';
5 |
6 | var FOCUSABLE_ELEMENTS = [
7 | 'a[href]:not([tabindex^="-"]):not([inert])',
8 | 'area[href]:not([tabindex^="-"]):not([inert])',
9 | 'input:not([disabled]):not([inert])',
10 | 'select:not([disabled]):not([inert])',
11 | 'textarea:not([disabled]):not([inert])',
12 | 'button:not([disabled]):not([inert])',
13 | 'iframe:not([tabindex^="-"]):not([inert])',
14 | 'audio:not([tabindex^="-"]):not([inert])',
15 | 'video:not([tabindex^="-"]):not([inert])',
16 | '[contenteditable]:not([tabindex^="-"]):not([inert])',
17 | '[tabindex]:not([tabindex^="-"]):not([inert])'
18 | ];
19 | var TAB_KEY = 9;
20 | var ESCAPE_KEY = 27;
21 | var focusedBeforeDialog;
22 |
23 | /**
24 | * Define the constructor to instantiate a dialog
25 | *
26 | * @constructor
27 | * @param {Element} node
28 | * @param {(NodeList | Element | string)} targets
29 | */
30 | function A11yDialog(node, targets) {
31 | // Prebind the functions that will be bound in addEventListener and
32 | // removeEventListener to avoid losing references
33 | this._show = this.show.bind(this);
34 | this._hide = this.hide.bind(this);
35 | this._maintainFocus = this._maintainFocus.bind(this);
36 | this._bindKeypress = this._bindKeypress.bind(this);
37 |
38 | // Keep a reference of the node and the actual dialog on the instance
39 | this.container = node;
40 | this.dialog = node.querySelector('dialog, [role="dialog"], [role="alertdialog"]');
41 | this.role = this.dialog.getAttribute('role') || 'dialog';
42 | this.useDialog = (
43 | 'show' in document.createElement('dialog') &&
44 | this.dialog.nodeName === 'DIALOG'
45 | );
46 |
47 | // Keep an object of listener types mapped to callback functions
48 | this._listeners = {};
49 |
50 | // Initialise everything needed for the dialog to work properly
51 | this.create(targets);
52 | }
53 |
54 | /**
55 | * Set up everything necessary for the dialog to be functioning
56 | *
57 | * @param {(NodeList | Element | string)} targets
58 | * @return {this}
59 | */
60 | A11yDialog.prototype.create = function(targets) {
61 | // Keep a collection of nodes to disable/enable when toggling the dialog
62 | this._targets =
63 | this._targets || collect(targets) || getSiblings(this.container);
64 |
65 | // Set the `shown` property to match the status from the DOM
66 | this.shown = this.dialog.hasAttribute('open');
67 |
68 | // Despite using a `` element, `role="dialog"` is not necessarily
69 | // implied by all screen-readers (yet)
70 | // See: https://github.com/edenspiekermann/a11y-dialog/commit/6ba711a777aed0dbda0719a18a02f742098c64d9#commitcomment-28694166
71 | this.dialog.setAttribute('role', this.role);
72 |
73 | if (!this.useDialog) {
74 | if (this.shown) {
75 | this.container.removeAttribute('aria-hidden');
76 | } else {
77 | this.container.setAttribute('aria-hidden', true);
78 | }
79 | } else {
80 | this.container.setAttribute('data-a11y-dialog-native', '');
81 | }
82 |
83 | // Keep a collection of dialog openers, each of which will be bound a click
84 | // event listener to open the dialog
85 | this._openers = $$('[data-a11y-dialog-show="' + this.container.id + '"]');
86 | this._openers.forEach(
87 | function(opener) {
88 | opener.addEventListener('click', this._show);
89 | }.bind(this)
90 | );
91 |
92 | // Keep a collection of dialog closers, each of which will be bound a click
93 | // event listener to close the dialog
94 | this._closers = $$('[data-a11y-dialog-hide]', this.container).concat(
95 | $$('[data-a11y-dialog-hide="' + this.container.id + '"]')
96 | );
97 | this._closers.forEach(
98 | function(closer) {
99 | closer.addEventListener('click', this._hide);
100 | }.bind(this)
101 | );
102 |
103 | // Execute all callbacks registered for the `create` event
104 | this._fire('create');
105 |
106 | return this;
107 | };
108 |
109 | /**
110 | * Show the dialog element, disable all the targets (siblings), trap the
111 | * current focus within it, listen for some specific key presses and fire all
112 | * registered callbacks for `show` event
113 | *
114 | * @param {Event} event
115 | * @return {this}
116 | */
117 | A11yDialog.prototype.show = function(event) {
118 | // If the dialog is already open, abort
119 | if (this.shown) {
120 | return this;
121 | }
122 |
123 | this.shown = true;
124 |
125 | // Keep a reference to the currently focused element to be able to restore
126 | // it later
127 | focusedBeforeDialog = document.activeElement;
128 |
129 | if (this.useDialog) {
130 | this.dialog.showModal(event instanceof Event ? void 0 : event);
131 | } else {
132 | this.dialog.setAttribute('open', '');
133 | this.container.removeAttribute('aria-hidden');
134 |
135 | // Iterate over the targets to disable them by setting their `aria-hidden`
136 | // attribute to `true`
137 | this._targets.forEach(function(target) {
138 | target.setAttribute('aria-hidden', 'true');
139 | });
140 | }
141 |
142 | // Set the focus to the first focusable child of the dialog element
143 | setFocusToFirstItem(this.dialog);
144 |
145 | // Bind a focus event listener to the body element to make sure the focus
146 | // stays trapped inside the dialog while open, and start listening for some
147 | // specific key presses (TAB and ESC)
148 | document.body.addEventListener('focus', this._maintainFocus, true);
149 | document.addEventListener('keydown', this._bindKeypress);
150 |
151 | // Execute all callbacks registered for the `show` event
152 | this._fire('show', event);
153 |
154 | return this;
155 | };
156 |
157 | /**
158 | * Hide the dialog element, enable all the targets (siblings), restore the
159 | * focus to the previously active element, stop listening for some specific
160 | * key presses and fire all registered callbacks for `hide` event
161 | *
162 | * @param {Event} event
163 | * @return {this}
164 | */
165 | A11yDialog.prototype.hide = function(event) {
166 | // If the dialog is already closed, abort
167 | if (!this.shown) {
168 | return this;
169 | }
170 |
171 | this.shown = false;
172 |
173 | if (this.useDialog) {
174 | this.dialog.close(event instanceof Event ? void 0 : event);
175 | } else {
176 | this.dialog.removeAttribute('open');
177 | this.container.setAttribute('aria-hidden', 'true');
178 |
179 | // Iterate over the targets to enable them by remove their `aria-hidden`
180 | // attribute
181 | this._targets.forEach(function(target) {
182 | target.removeAttribute('aria-hidden');
183 | });
184 | }
185 |
186 | // If their was a focused element before the dialog was opened, restore the
187 | // focus back to it
188 | if (focusedBeforeDialog) {
189 | focusedBeforeDialog.focus();
190 | }
191 |
192 | // Remove the focus event listener to the body element and stop listening
193 | // for specific key presses
194 | document.body.removeEventListener('focus', this._maintainFocus, true);
195 | document.removeEventListener('keydown', this._bindKeypress);
196 |
197 | // Execute all callbacks registered for the `hide` event
198 | this._fire('hide', event);
199 |
200 | return this;
201 | };
202 |
203 | /**
204 | * Destroy the current instance (after making sure the dialog has been hidden)
205 | * and remove all associated listeners from dialog openers and closers
206 | *
207 | * @return {this}
208 | */
209 | A11yDialog.prototype.destroy = function() {
210 | // Hide the dialog to avoid destroying an open instance
211 | this.hide();
212 |
213 | // Remove the click event listener from all dialog openers
214 | this._openers.forEach(
215 | function(opener) {
216 | opener.removeEventListener('click', this._show);
217 | }.bind(this)
218 | );
219 |
220 | // Remove the click event listener from all dialog closers
221 | this._closers.forEach(
222 | function(closer) {
223 | closer.removeEventListener('click', this._hide);
224 | }.bind(this)
225 | );
226 |
227 | // Execute all callbacks registered for the `destroy` event
228 | this._fire('destroy');
229 |
230 | // Keep an object of listener types mapped to callback functions
231 | this._listeners = {};
232 |
233 | return this;
234 | };
235 |
236 | /**
237 | * Register a new callback for the given event type
238 | *
239 | * @param {string} type
240 | * @param {Function} handler
241 | */
242 | A11yDialog.prototype.on = function(type, handler) {
243 | if (typeof this._listeners[type] === 'undefined') {
244 | this._listeners[type] = [];
245 | }
246 |
247 | this._listeners[type].push(handler);
248 |
249 | return this;
250 | };
251 |
252 | /**
253 | * Unregister an existing callback for the given event type
254 | *
255 | * @param {string} type
256 | * @param {Function} handler
257 | */
258 | A11yDialog.prototype.off = function(type, handler) {
259 | var index = this._listeners[type].indexOf(handler);
260 |
261 | if (index > -1) {
262 | this._listeners[type].splice(index, 1);
263 | }
264 |
265 | return this;
266 | };
267 |
268 | /**
269 | * Iterate over all registered handlers for given type and call them all with
270 | * the dialog element as first argument, event as second argument (if any).
271 | *
272 | * @access private
273 | * @param {string} type
274 | * @param {Event} event
275 | */
276 | A11yDialog.prototype._fire = function(type, event) {
277 | var listeners = this._listeners[type] || [];
278 |
279 | listeners.forEach(
280 | function(listener) {
281 | listener(this.container, event);
282 | }.bind(this)
283 | );
284 | };
285 |
286 | /**
287 | * Private event handler used when listening to some specific key presses
288 | * (namely ESCAPE and TAB)
289 | *
290 | * @access private
291 | * @param {Event} event
292 | */
293 | A11yDialog.prototype._bindKeypress = function(event) {
294 | // If the dialog is shown and the ESCAPE key is being pressed, prevent any
295 | // further effects from the ESCAPE key and hide the dialog, unless its role
296 | // is 'alertdialog', which should be modal
297 | if (this.shown && event.which === ESCAPE_KEY && this.role !== 'alertdialog') {
298 | event.preventDefault();
299 | this.hide();
300 | }
301 |
302 | // If the dialog is shown and the TAB key is being pressed, make sure the
303 | // focus stays trapped within the dialog element
304 | if (this.shown && event.which === TAB_KEY) {
305 | trapTabKey(this.dialog, event);
306 | }
307 | };
308 |
309 | /**
310 | * Private event handler used when making sure the focus stays within the
311 | * currently open dialog
312 | *
313 | * @access private
314 | * @param {Event} event
315 | */
316 | A11yDialog.prototype._maintainFocus = function(event) {
317 | // If the dialog is shown and the focus is not within the dialog element,
318 | // move it back to its first focusable child
319 | if (this.shown && !this.container.contains(event.target)) {
320 | setFocusToFirstItem(this.dialog);
321 | }
322 | };
323 |
324 | /**
325 | * Convert a NodeList into an array
326 | *
327 | * @param {NodeList} collection
328 | * @return {Array}
329 | */
330 | function toArray(collection) {
331 | return Array.prototype.slice.call(collection);
332 | }
333 |
334 | /**
335 | * Query the DOM for nodes matching the given selector, scoped to context (or
336 | * the whole document)
337 | *
338 | * @param {String} selector
339 | * @param {Element} [context = document]
340 | * @return {Array}
341 | */
342 | function $$(selector, context) {
343 | return toArray((context || document).querySelectorAll(selector));
344 | }
345 |
346 | /**
347 | * Return an array of Element based on given argument (NodeList, Element or
348 | * string representing a selector)
349 | *
350 | * @param {(NodeList | Element | string)} target
351 | * @return {Array}
352 | */
353 | function collect(target) {
354 | if (NodeList.prototype.isPrototypeOf(target)) {
355 | return toArray(target);
356 | }
357 |
358 | if (Element.prototype.isPrototypeOf(target)) {
359 | return [target];
360 | }
361 |
362 | if (typeof target === 'string') {
363 | return $$(target);
364 | }
365 | }
366 |
367 | /**
368 | * Set the focus to the first element with `autofocus` or the first focusable
369 | * child of the given element
370 | *
371 | * @param {Element} node
372 | */
373 | function setFocusToFirstItem(node) {
374 | var focusableChildren = getFocusableChildren(node);
375 | var focused = node.querySelector('[autofocus]') || focusableChildren[0];
376 |
377 | if (focused) {
378 | focused.focus();
379 | }
380 | }
381 |
382 | /**
383 | * Get the focusable children of the given element
384 | *
385 | * @param {Element} node
386 | * @return {Array}
387 | */
388 | function getFocusableChildren(node) {
389 | return $$(FOCUSABLE_ELEMENTS.join(','), node).filter(function(child) {
390 | return !!(
391 | child.offsetWidth ||
392 | child.offsetHeight ||
393 | child.getClientRects().length
394 | );
395 | });
396 | }
397 |
398 | /**
399 | * Trap the focus inside the given element
400 | *
401 | * @param {Element} node
402 | * @param {Event} event
403 | */
404 | function trapTabKey(node, event) {
405 | var focusableChildren = getFocusableChildren(node);
406 | var focusedItemIndex = focusableChildren.indexOf(document.activeElement);
407 |
408 | // If the SHIFT key is being pressed while tabbing (moving backwards) and
409 | // the currently focused item is the first one, move the focus to the last
410 | // focusable item from the dialog element
411 | if (event.shiftKey && focusedItemIndex === 0) {
412 | focusableChildren[focusableChildren.length - 1].focus();
413 | event.preventDefault();
414 | // If the SHIFT key is not being pressed (moving forwards) and the currently
415 | // focused item is the last one, move the focus to the first focusable item
416 | // from the dialog element
417 | } else if (
418 | !event.shiftKey &&
419 | focusedItemIndex === focusableChildren.length - 1
420 | ) {
421 | focusableChildren[0].focus();
422 | event.preventDefault();
423 | }
424 | }
425 |
426 | /**
427 | * Retrieve siblings from given element
428 | *
429 | * @param {Element} node
430 | * @return {Array}
431 | */
432 | function getSiblings(node) {
433 | var nodes = toArray(node.parentNode.childNodes);
434 | var siblings = nodes.filter(function(node) {
435 | return node.nodeType === 1;
436 | });
437 |
438 | siblings.splice(siblings.indexOf(node), 1);
439 |
440 | return siblings;
441 | }
442 |
443 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
444 | module.exports = A11yDialog;
445 | } else if (typeof define === 'function' && define.amd) {
446 | define('A11yDialog', [], function() {
447 | return A11yDialog;
448 | });
449 | } else if (typeof global === 'object') {
450 | global.A11yDialog = A11yDialog;
451 | }
452 | })(typeof global !== 'undefined' ? global : window);
453 |
--------------------------------------------------------------------------------
/external/a11y-dialog/a11y-dialog.min.js:
--------------------------------------------------------------------------------
1 | /*! a11y-dialog 5.2.0 — © Edenspiekermann */
2 | !function(t){"use strict";function i(t,i){this._show=this.show.bind(this),this._hide=this.hide.bind(this),this._maintainFocus=this._maintainFocus.bind(this),this._bindKeypress=this._bindKeypress.bind(this),this.container=t,this.dialog=t.querySelector('dialog, [role="dialog"], [role="alertdialog"]'),this.role=this.dialog.getAttribute("role")||"dialog",this.useDialog="show"in document.createElement("dialog")&&"DIALOG"===this.dialog.nodeName,this._listeners={},this.create(i)}function e(t){return Array.prototype.slice.call(t)}function n(t,i){return e((i||document).querySelectorAll(t))}function o(t){return NodeList.prototype.isPrototypeOf(t)?e(t):Element.prototype.isPrototypeOf(t)?[t]:"string"==typeof t?n(t):void 0}function s(t){var i=r(t),e=t.querySelector("[autofocus]")||i[0];e&&e.focus()}function r(t){return n(c.join(","),t).filter(function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)})}function h(t,i){var e=r(t),n=e.indexOf(document.activeElement);i.shiftKey&&0===n?(e[e.length-1].focus(),i.preventDefault()):i.shiftKey||n!==e.length-1||(e[0].focus(),i.preventDefault())}function a(t){var i=e(t.parentNode.childNodes),n=i.filter(function(t){return 1===t.nodeType});return n.splice(n.indexOf(t),1),n}var d,c=['a[href]:not([tabindex^="-"]):not([inert])','area[href]:not([tabindex^="-"]):not([inert])',"input:not([disabled]):not([inert])","select:not([disabled]):not([inert])","textarea:not([disabled]):not([inert])","button:not([disabled]):not([inert])",'iframe:not([tabindex^="-"]):not([inert])','audio:not([tabindex^="-"]):not([inert])','video:not([tabindex^="-"]):not([inert])','[contenteditable]:not([tabindex^="-"]):not([inert])','[tabindex]:not([tabindex^="-"]):not([inert])'];i.prototype.create=function(t){return this._targets=this._targets||o(t)||a(this.container),this.shown=this.dialog.hasAttribute("open"),this.dialog.setAttribute("role",this.role),this.useDialog?this.container.setAttribute("data-a11y-dialog-native",""):this.shown?this.container.removeAttribute("aria-hidden"):this.container.setAttribute("aria-hidden",!0),this._openers=n('[data-a11y-dialog-show="'+this.container.id+'"]'),this._openers.forEach(function(t){t.addEventListener("click",this._show)}.bind(this)),this._closers=n("[data-a11y-dialog-hide]",this.container).concat(n('[data-a11y-dialog-hide="'+this.container.id+'"]')),this._closers.forEach(function(t){t.addEventListener("click",this._hide)}.bind(this)),this._fire("create"),this},i.prototype.show=function(t){return this.shown?this:(this.shown=!0,d=document.activeElement,this.useDialog?this.dialog.showModal(t instanceof Event?void 0:t):(this.dialog.setAttribute("open",""),this.container.removeAttribute("aria-hidden"),this._targets.forEach(function(t){t.setAttribute("aria-hidden","true")})),s(this.dialog),document.body.addEventListener("focus",this._maintainFocus,!0),document.addEventListener("keydown",this._bindKeypress),this._fire("show",t),this)},i.prototype.hide=function(t){return this.shown?(this.shown=!1,this.useDialog?this.dialog.close(t instanceof Event?void 0:t):(this.dialog.removeAttribute("open"),this.container.setAttribute("aria-hidden","true"),this._targets.forEach(function(t){t.removeAttribute("aria-hidden")})),d&&d.focus(),document.body.removeEventListener("focus",this._maintainFocus,!0),document.removeEventListener("keydown",this._bindKeypress),this._fire("hide",t),this):this},i.prototype.destroy=function(){return this.hide(),this._openers.forEach(function(t){t.removeEventListener("click",this._show)}.bind(this)),this._closers.forEach(function(t){t.removeEventListener("click",this._hide)}.bind(this)),this._fire("destroy"),this._listeners={},this},i.prototype.on=function(t,i){return void 0===this._listeners[t]&&(this._listeners[t]=[]),this._listeners[t].push(i),this},i.prototype.off=function(t,i){var e=this._listeners[t].indexOf(i);return e>-1&&this._listeners[t].splice(e,1),this},i.prototype._fire=function(t,i){(this._listeners[t]||[]).forEach(function(t){t(this.container,i)}.bind(this))},i.prototype._bindKeypress=function(t){this.shown&&27===t.which&&"alertdialog"!==this.role&&(t.preventDefault(),this.hide()),this.shown&&9===t.which&&h(this.dialog,t)},i.prototype._maintainFocus=function(t){this.shown&&!this.container.contains(t.target)&&s(this.dialog)},"undefined"!=typeof module&&void 0!==module.exports?module.exports=i:"function"==typeof define&&define.amd?define("A11yDialog",[],function(){return i}):"object"==typeof t&&(t.A11yDialog=i)}("undefined"!=typeof global?global:window);
3 |
--------------------------------------------------------------------------------
/external/a11y-dialog/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "_from": "a11y-dialog",
3 | "_id": "a11y-dialog@5.2.0",
4 | "_inBundle": false,
5 | "_integrity": "sha512-vymlarVdoDKNwQPq513D5IANZu7fdOiWjQJG0FuEFI77RfJUGrxpfI6puwXy7hxKmVTSf4bNq6ZgCb+EikIl8g==",
6 | "_location": "/a11y-dialog",
7 | "_phantomChildren": {},
8 | "_requested": {
9 | "type": "tag",
10 | "registry": true,
11 | "raw": "a11y-dialog",
12 | "name": "a11y-dialog",
13 | "escapedName": "a11y-dialog",
14 | "rawSpec": "",
15 | "saveSpec": null,
16 | "fetchSpec": "latest"
17 | },
18 | "_requiredBy": [
19 | "#USER",
20 | "/"
21 | ],
22 | "_resolved": "https://registry.npmjs.org/a11y-dialog/-/a11y-dialog-5.2.0.tgz",
23 | "_shasum": "bc3f9ccb7154a840bffd61b9385edbd093f7f209",
24 | "_spec": "a11y-dialog",
25 | "_where": "C:\\wamp64\\www\\other",
26 | "author": {
27 | "name": "Hugo Giraudel",
28 | "url": "https://hugogiraudel.com"
29 | },
30 | "bugs": {
31 | "url": "https://github.com/edenspiekermann/a11y-dialog/issues"
32 | },
33 | "bundleDependencies": false,
34 | "deprecated": false,
35 | "description": "A tiny script to make dialog windows accessible to assistive technology users.",
36 | "devDependencies": {
37 | "husky": "^0.14.3",
38 | "lint-staged": "^6.0.0",
39 | "prettier": "^1.10.2",
40 | "semistandard": "^7.0.5",
41 | "uglify-js": "^2.6.1"
42 | },
43 | "files": [
44 | "a11y-dialog.js",
45 | "a11y-dialog.min.js"
46 | ],
47 | "homepage": "https://github.com/edenspiekermann/a11y-dialog",
48 | "keywords": [
49 | "modal",
50 | "dialog",
51 | "accessibility",
52 | "a11y",
53 | "focus"
54 | ],
55 | "license": "MIT",
56 | "lint-staged": {
57 | "*.js": [
58 | "prettier --no-semi --single-quote --print-width 80 --write",
59 | "git add",
60 | "eslint --fix",
61 | "git add"
62 | ]
63 | },
64 | "main": "a11y-dialog.js",
65 | "name": "a11y-dialog",
66 | "repository": {
67 | "type": "git",
68 | "url": "git+https://github.com/edenspiekermann/a11y-dialog.git"
69 | },
70 | "scripts": {
71 | "add-version": "echo \"/*! a11y-dialog $(npm run extract-version --silent) — © Edenspiekermann */\n$(cat a11y-dialog.min.js)\" > a11y-dialog.min.js",
72 | "build": "npm run minify && npm run copy",
73 | "compress": "gzip -9 -fkc a11y-dialog.min.js > a11y-dialog.min.js.gz",
74 | "copy": "cp a11y-dialog.js example/main.js",
75 | "docs:build": "npm run docs:prepare && gitbook build",
76 | "docs:clean": "rimraf _book",
77 | "docs:prepare": "gitbook install",
78 | "docs:publish": "npm run docs:clean && npm run docs:build && cd _book && git init && git commit --allow-empty -m 'Update book' && git checkout -b gh-pages && touch .nojekyll && git add . && git commit -am 'Update book' && git push git@github.com:edenspiekermann/a11y-dialog gh-pages --force",
79 | "docs:watch": "npm run docs:prepare && gitbook serve",
80 | "extract-version": "cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]'",
81 | "lint": "semistandard a11y-dialog.js",
82 | "minify": "uglifyjs a11y-dialog.js -o a11y-dialog.min.js -c -m",
83 | "postbuild": "npm run add-version",
84 | "show": "ls -lh a11y-dialog.min.js.gz | awk '{print \"Gzipped script size:\", $5\"B\"}'",
85 | "size": "npm run build --silent && npm run compress --silent && npm run show --silent && rm a11y-dialog.min.js.gz",
86 | "test": "open tests/index.html"
87 | },
88 | "version": "5.2.0"
89 | }
90 |
--------------------------------------------------------------------------------
/external/codemirror/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (C) 2017 by Marijn Haverbeke and others
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/external/codemirror/codemirror.css:
--------------------------------------------------------------------------------
1 | /* BASICS */
2 |
3 | .CodeMirror {
4 | /* Set height, width, borders, and global font properties here */
5 | font-family: monospace;
6 | height: auto;
7 | color: black;
8 | direction: ltr;
9 | }
10 |
11 | /* PADDING */
12 |
13 | .CodeMirror-lines {
14 | padding: 4px 0; /* Vertical padding around content */
15 | }
16 | .CodeMirror pre {
17 | padding: 0 4px; /* Horizontal padding of content */
18 | }
19 |
20 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
21 | background-color: white; /* The little square between H and V scrollbars */
22 | }
23 |
24 | .CodeMirror-error {
25 | background-color: #F6CECE;
26 | }
27 |
28 | /* GUTTER */
29 |
30 | .CodeMirror-gutters {
31 | border-right: 1px solid #ddd;
32 | background-color: #f7f7f7;
33 | white-space: nowrap;
34 | }
35 | .CodeMirror-linenumbers {}
36 | .CodeMirror-linenumber {
37 | padding: 0 3px 0 5px;
38 | min-width: 20px;
39 | text-align: right;
40 | color: #999;
41 | white-space: nowrap;
42 | }
43 |
44 | .CodeMirror-guttermarker { color: black; }
45 | .CodeMirror-guttermarker-subtle { color: #999; }
46 |
47 | /* CURSOR */
48 |
49 | .CodeMirror-cursor {
50 | border-left: 1px solid black;
51 | border-right: none;
52 | width: 0;
53 | }
54 | /* Shown when moving in bi-directional text */
55 | .CodeMirror div.CodeMirror-secondarycursor {
56 | border-left: 1px solid silver;
57 | }
58 | .cm-fat-cursor .CodeMirror-cursor {
59 | width: auto;
60 | border: 0 !important;
61 | background: #7e7;
62 | }
63 | .cm-fat-cursor div.CodeMirror-cursors {
64 | z-index: 1;
65 | }
66 | .cm-fat-cursor-mark {
67 | background-color: rgba(20, 255, 20, 0.5);
68 | -webkit-animation: blink 1.06s steps(1) infinite;
69 | -moz-animation: blink 1.06s steps(1) infinite;
70 | animation: blink 1.06s steps(1) infinite;
71 | }
72 | .cm-animate-fat-cursor {
73 | width: auto;
74 | border: 0;
75 | -webkit-animation: blink 1.06s steps(1) infinite;
76 | -moz-animation: blink 1.06s steps(1) infinite;
77 | animation: blink 1.06s steps(1) infinite;
78 | background-color: #7e7;
79 | }
80 | @-moz-keyframes blink {
81 | 0% {}
82 | 50% { background-color: transparent; }
83 | 100% {}
84 | }
85 | @-webkit-keyframes blink {
86 | 0% {}
87 | 50% { background-color: transparent; }
88 | 100% {}
89 | }
90 | @keyframes blink {
91 | 0% {}
92 | 50% { background-color: transparent; }
93 | 100% {}
94 | }
95 |
96 | /* Can style cursor different in overwrite (non-insert) mode */
97 | .CodeMirror-overwrite .CodeMirror-cursor {}
98 |
99 | .cm-tab { display: inline-block; text-decoration: inherit; }
100 |
101 | .CodeMirror-rulers {
102 | position: absolute;
103 | left: 0; right: 0; top: -50px; bottom: -20px;
104 | overflow: hidden;
105 | }
106 | .CodeMirror-ruler {
107 | border-left: 1px solid #ccc;
108 | top: 0; bottom: 0;
109 | position: absolute;
110 | }
111 |
112 | /* DEFAULT THEME */
113 |
114 | .cm-s-default .cm-header {color: blue;}
115 | .cm-s-default .cm-quote {color: #090;}
116 | .cm-negative {color: #d44;}
117 | .cm-positive {color: #292;}
118 | .cm-header, .cm-strong {font-weight: bold;}
119 | .cm-em {font-style: italic;}
120 | .cm-link {text-decoration: underline;}
121 | .cm-strikethrough {text-decoration: line-through;}
122 |
123 | .cm-s-default .cm-keyword {color: #708;}
124 | .cm-s-default .cm-atom {color: #219;}
125 | .cm-s-default .cm-number {color: #164;}
126 | .cm-s-default .cm-def {color: #00f;}
127 | .cm-s-default .cm-variable,
128 | .cm-s-default .cm-punctuation,
129 | .cm-s-default .cm-property,
130 | .cm-s-default .cm-operator {}
131 | .cm-s-default .cm-variable-2 {color: #05a;}
132 | .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
133 | .cm-s-default .cm-comment {color: #a50;}
134 | .cm-s-default .cm-string {color: #a11;}
135 | .cm-s-default .cm-string-2 {color: #f50;}
136 | .cm-s-default .cm-meta {color: #555;}
137 | .cm-s-default .cm-qualifier {color: #555;}
138 | .cm-s-default .cm-builtin {color: #30a;}
139 | .cm-s-default .cm-bracket {color: #997;}
140 | .cm-s-default .cm-tag {color: #170;}
141 | .cm-s-default .cm-attribute {color: #00c;}
142 | .cm-s-default .cm-hr {color: #999;}
143 | .cm-s-default .cm-link {color: #00c;}
144 |
145 | .cm-s-default .cm-error {color: #f00;}
146 | .cm-invalidchar {color: #f00;}
147 |
148 | .CodeMirror-composing { border-bottom: 2px solid; }
149 |
150 | /* Default styles for common addons */
151 |
152 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
153 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
154 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
155 | .CodeMirror-activeline-background {background: #e8f2ff;}
156 |
157 | /* STOP */
158 |
159 | /* The rest of this file contains styles related to the mechanics of
160 | the editor. You probably shouldn't touch them. */
161 |
162 | .CodeMirror {
163 | position: relative;
164 | overflow: hidden;
165 | background: white;
166 | }
167 |
168 | .CodeMirror-scroll {
169 | overflow: scroll !important; /* Things will break if this is overridden */
170 | /* 30px is the magic margin used to hide the element's real scrollbars */
171 | /* See overflow: hidden in .CodeMirror */
172 | margin-bottom: -30px; margin-right: -30px;
173 | padding-bottom: 30px;
174 | height: 100%;
175 | outline: none; /* Prevent dragging from highlighting the element */
176 | position: relative;
177 | min-height:100px;
178 | }
179 | .CodeMirror-sizer {
180 | position: relative;
181 | border-right: 30px solid transparent;
182 | }
183 |
184 | /* The fake, visible scrollbars. Used to force redraw during scrolling
185 | before actual scrolling happens, thus preventing shaking and
186 | flickering artifacts. */
187 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
188 | position: absolute;
189 | z-index: 6;
190 | display: none;
191 | }
192 | .CodeMirror-vscrollbar {
193 | right: 0; top: 0;
194 | overflow-x: hidden;
195 | overflow-y: scroll;
196 | }
197 | .CodeMirror-hscrollbar {
198 | bottom: 0; left: 0;
199 | overflow-y: hidden;
200 | overflow-x: scroll;
201 | }
202 | .CodeMirror-scrollbar-filler {
203 | right: 0; bottom: 0;
204 | }
205 | .CodeMirror-gutter-filler {
206 | left: 0; bottom: 0;
207 | }
208 |
209 | .CodeMirror-gutters {
210 | position: absolute; left: 0; top: 0;
211 | min-height: 100%;
212 | z-index: 3;
213 | }
214 | .CodeMirror-gutter {
215 | white-space: normal;
216 | height: 100%;
217 | display: inline-block;
218 | vertical-align: top;
219 | margin-bottom: -30px;
220 | }
221 | .CodeMirror-gutter-wrapper {
222 | position: absolute;
223 | z-index: 4;
224 | background: none !important;
225 | border: none !important;
226 | }
227 | .CodeMirror-gutter-background {
228 | position: absolute;
229 | top: 0; bottom: 0;
230 | z-index: 4;
231 | }
232 | .CodeMirror-gutter-elt {
233 | position: absolute;
234 | cursor: default;
235 | z-index: 4;
236 | }
237 | .CodeMirror-gutter-wrapper ::selection { background-color: transparent }
238 | .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
239 |
240 | .CodeMirror-lines {
241 | cursor: text;
242 | min-height: 1px; /* prevents collapsing before first draw */
243 | }
244 | .CodeMirror pre {
245 | /* Reset some styles that the rest of the page might have set */
246 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
247 | border-width: 0;
248 | background: transparent;
249 | font-family: inherit;
250 | font-size: inherit;
251 | margin: 0;
252 | white-space: pre;
253 | word-wrap: normal;
254 | line-height: inherit;
255 | color: inherit;
256 | z-index: 2;
257 | position: relative;
258 | overflow: visible;
259 | -webkit-tap-highlight-color: transparent;
260 | -webkit-font-variant-ligatures: contextual;
261 | font-variant-ligatures: contextual;
262 | }
263 | .CodeMirror-wrap pre {
264 | word-wrap: break-word;
265 | white-space: pre-wrap;
266 | word-break: normal;
267 | }
268 |
269 | .CodeMirror-linebackground {
270 | position: absolute;
271 | left: 0; right: 0; top: 0; bottom: 0;
272 | z-index: 0;
273 | }
274 |
275 | .CodeMirror-linewidget {
276 | position: relative;
277 | z-index: 2;
278 | overflow: auto;
279 | }
280 |
281 | .CodeMirror-widget {}
282 |
283 | .CodeMirror-rtl pre { direction: rtl; }
284 |
285 | .CodeMirror-code {
286 | outline: none;
287 | }
288 |
289 | /* Force content-box sizing for the elements where we expect it */
290 | .CodeMirror-scroll,
291 | .CodeMirror-sizer,
292 | .CodeMirror-gutter,
293 | .CodeMirror-gutters,
294 | .CodeMirror-linenumber {
295 | -moz-box-sizing: content-box;
296 | box-sizing: content-box;
297 | }
298 |
299 | .CodeMirror-measure {
300 | position: absolute;
301 | width: 100%;
302 | height: 0;
303 | overflow: hidden;
304 | visibility: hidden;
305 | }
306 |
307 | .CodeMirror-cursor {
308 | position: absolute;
309 | pointer-events: none;
310 | }
311 | .CodeMirror-measure pre { position: static; }
312 |
313 | div.CodeMirror-cursors {
314 | visibility: hidden;
315 | position: relative;
316 | z-index: 3;
317 | }
318 | div.CodeMirror-dragcursors {
319 | visibility: visible;
320 | }
321 |
322 | .CodeMirror-focused div.CodeMirror-cursors {
323 | visibility: visible;
324 | }
325 |
326 | .CodeMirror-selected { background: #d9d9d9; }
327 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
328 | .CodeMirror-crosshair { cursor: crosshair; }
329 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
330 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
331 |
332 | .cm-searching {
333 | background-color: #ffa;
334 | background-color: rgba(255, 255, 0, .4);
335 | }
336 |
337 | /* Used to force a border model for a node */
338 | .cm-force-border { padding-right: .1px; }
339 |
340 | @media print {
341 | /* Hide the cursor when printing */
342 | .CodeMirror div.CodeMirror-cursors {
343 | visibility: hidden;
344 | }
345 | }
346 |
347 | /* See issue #2901 */
348 | .cm-tab-wrap-hack:after { content: ''; }
349 |
350 | /* Help users use markselection to safely style text background */
351 | span.CodeMirror-selectedtext { background: none; }
352 |
--------------------------------------------------------------------------------
/external/codemirror/mode/sql/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: SQL Mode for CodeMirror
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
32 |
33 |
34 | SQL Mode for CodeMirror
35 |
52 | MIME types defined:
53 | text/x-sql
,
54 | text/x-mysql
,
55 | text/x-mariadb
,
56 | text/x-cassandra
,
57 | text/x-plsql
,
58 | text/x-mssql
,
59 | text/x-hive
,
60 | text/x-pgsql
,
61 | text/x-gql
,
62 | text/x-gpsql
.
63 | text/x-esper
.
64 |
65 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/external/codemirror/mode/sql/sql.js:
--------------------------------------------------------------------------------
1 | (function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)})(function(e){e.defineMode("sql",function(l,g){function k(c,b){var d=c.next();if(m[d]){var e=m[d](c,b);if(!1!==e)return e}if(h.hexNumber&&("0"==d&&c.match(/^[xX][0-9a-fA-F]+/)||("x"==d||"X"==d)&&c.match(/^'[0-9a-fA-F]+'/))||h.binaryNumber&&(("b"==d||"B"==d)&&c.match(/^'[01]+'/)||"0"==d&&c.match(/^b[01]+/)))return"number";
2 | if(47d.charCodeAt(0))return c.match(/^[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?/),h.decimallessFloat&&c.match(/^\.(?!\.)/),"number";if("?"==d&&(c.eatSpace()||c.eol()||c.eat(";")))return"variable-3";if("'"==d||'"'==d&&h.doubleQuote)return b.tokenize=a(d),b.tokenize(c,b);if(!(h.nCharCast&&("n"==d||"N"==d)||h.charsetCast&&"_"==d&&c.match(/[a-z][a-z0-9]*/i))||"'"!=c.peek()&&'"'!=c.peek()){if(/^[\(\),;\[\]]/.test(d))return null;if(h.commentSlashSlash&&"/"==d&&c.eat("/")||h.commentHash&&
3 | "#"==d||"-"==d&&c.eat("-")&&(!h.commentSpaceRequired||c.eat(" ")))return c.skipToEnd(),"comment";if("/"==d&&c.eat("*"))return b.tokenize=f(1),b.tokenize(c,b);if("."==d){if(h.zerolessFloat&&c.match(/^(?:\d+(?:e[+-]?\d+)?)/i))return"number";if(c.match(/^\.+/))return null;if(h.ODBCdotTable&&c.match(/^[\w\d_]+/))return"variable-2"}else{if(n.test(d))return c.eatWhile(n),null;if("{"==d&&(c.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/)||c.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/)))return"number";c.eatWhile(/^[_\w\d]/);
4 | b=c.current().toLowerCase();return q.hasOwnProperty(b)&&(c.match(/^( )+'[^']*'/)||c.match(/^( )+"[^"]*"/))?"number":r.hasOwnProperty(b)?"atom":t.hasOwnProperty(b)?"builtin":u.hasOwnProperty(b)?"keyword":v.hasOwnProperty(b)?"string-2":null}}else return"keyword"}function a(a){return function(c,f){for(var b=!1,d;null!=(d=c.next());){if(d==a&&!b){f.tokenize=k;break}b=!b&&"\\"==d}return"string"}}function f(a){return function(c,d){var b=c.match(/^.*?(\/\*|\*\/)/);b?d.tokenize="/*"==b[1]?f(a+1):1!=&|~^]/,h=g.support||{},m=g.hooks||{},q=g.dateSQL||{date:!0,time:!0,timestamp:!0};return{startState:function(){return{tokenize:k,context:null}},token:function(a,b){a.sol()&&b.context&&null==b.context.align&&(b.context.align=!1);if(b.tokenize==k&&a.eatSpace())return null;
6 | var c=b.tokenize(a,b);if("comment"==c)return c;b.context&&null==b.context.align&&(b.context.align=!0);var f=a.current();"("==f?p(a,b,")"):"["==f?p(a,b,"]"):b.context&&b.context.type==f&&(b.indent=b.context.indent,b.context=b.context.prev);return c},indent:function(a,b){a=a.context;if(!a)return e.Pass;b=b.charAt(0)==a.type;return a.align?a.col+(b?0:1):a.indent+(b?0:l.indentUnit)},blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:h.commentSlashSlash?"//":h.commentHash?"#":"--"}});(function(){function l(a){for(var f;null!=
7 | (f=a.next());)if("`"==f&&!a.eat("`"))return"variable-2";a.backUp(a.current().length-1);return a.eatWhile(/\w/)?"variable-2":null}function g(a){a.eat("@")&&(a.match(/^session\./),a.match(/^local\./),a.match(/^global\./));return a.eat("'")?(a.match(/^.*'/),"variable-2"):a.eat('"')?(a.match(/^.*"/),"variable-2"):a.eat("`")?(a.match(/^.*`/),"variable-2"):a.match(/^[0-9a-zA-Z$\._]+/)?"variable-2":null}function k(a){return a.eat("N")?"atom":a.match(/^[a-zA-Z.#!?]/)?"variable-2":null}function a(a){var e=
8 | {};a=a.split(" ");for(var f=0;f !=]/,dateSQL:a("date time timestamp"),support:a("ODBCdotTable doubleQuote binaryNumber hexNumber")});e.defineMIME("text/x-mssql",{name:"sql",client:a("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered declare exec"),
10 | builtin:a("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=]/,dateSQL:a("date datetimeoffset datetime2 smalldatetime datetime time"),hooks:{"@":g}});e.defineMIME("text/x-mysql",{name:"sql",client:a("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
11 | keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group group_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
12 | builtin:a("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^]/,dateSQL:a("date time timestamp"),support:a("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
13 | hooks:{"@":g,"`":l,"\\":k}});e.defineMIME("text/x-mariadb",{name:"sql",client:a("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
14 | builtin:a("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^]/,dateSQL:a("date time timestamp"),support:a("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),
15 | hooks:{"@":g,"`":l,"\\":k}});e.defineMIME("text/x-sqlite",{name:"sql",client:a("auth backup bail binary changes check clone databases dbinfo dump echo eqp exit explain fullschema headers help import imposter indexes iotrace limit lint load log mode nullvalue once open output print prompt quit read restore save scanstats schema separator session shell show stats system tables testcase timeout timer trace vfsinfo vfslist vfsname width"),keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit abort action add after all analyze attach autoincrement before begin cascade case cast check collate column commit conflict constraint cross current_date current_time current_timestamp database default deferrable deferred detach each else end escape except exclusive exists explain fail for foreign full glob if ignore immediate index indexed initially inner instead intersect isnull key left limit match natural no notnull null of offset outer plan pragma primary query raise recursive references regexp reindex release rename replace restrict right rollback row savepoint temp temporary then to transaction trigger unique using vacuum view virtual when with without"),
16 | builtin:a("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text clob bigint int int2 int8 integer float double char varchar date datetime year unsigned signed numeric real"),atoms:a("null current_date current_time current_timestamp"),operatorChars:/^[*+\-%<>!=&|/~]/,dateSQL:a("date time timestamp datetime"),support:a("decimallessFloat zerolessFloat"),identifierQuote:'"',hooks:{"@":g,":":g,"?":g,$:g,'"':function(a){for(var e;null!=
17 | (e=a.next());)if('"'==e&&!a.eat('"'))return"variable-2";a.backUp(a.current().length-1);return a.eatWhile(/\w/)?"variable-2":null},"`":l}});e.defineMIME("text/x-cassandra",{name:"sql",client:{},keywords:a("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"),
18 | builtin:a("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"),atoms:a("false true infinity NaN"),operatorChars:/^[<>=]/,dateSQL:{},support:a("commentSlashSlash decimallessFloat"),hooks:{}});e.defineMIME("text/x-plsql",{name:"sql",client:a("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
19 | keywords:a("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
20 | builtin:a("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least length lengthb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),
21 | operatorChars:/^[*+\-%<>!=~]/,dateSQL:a("date time timestamp"),support:a("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")});e.defineMIME("text/x-hive",{name:"sql",keywords:a("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"),
22 | builtin:a("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=]/,dateSQL:a("date timestamp"),support:a("ODBCdotTable doubleQuote binaryNumber hexNumber")});e.defineMIME("text/x-pgsql",{name:"sql",client:a("source"),keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit a abort abs absent absolute access according action ada add admin after aggregate all allocate also always analyse analyze any are array array_agg array_max_cardinality asensitive assertion assignment asymmetric at atomic attribute attributes authorization avg backward base64 before begin begin_frame begin_partition bernoulli binary bit_length blob blocked bom both breadth c cache call called cardinality cascade cascaded case cast catalog catalog_name ceil ceiling chain characteristics characters character_length character_set_catalog character_set_name character_set_schema char_length check checkpoint class class_origin clob close cluster coalesce cobol collate collation collation_catalog collation_name collation_schema collect column columns column_name command_function command_function_code comment comments commit committed concurrently condition condition_number configuration conflict connect connection connection_name constraint constraints constraint_catalog constraint_name constraint_schema constructor contains content continue control conversion convert copy corr corresponding cost covar_pop covar_samp cross csv cube cume_dist current current_catalog current_date current_default_transform_group current_path current_role current_row current_schema current_time current_timestamp current_transform_group_for_type current_user cursor cursor_name cycle data database datalink datetime_interval_code datetime_interval_precision day db deallocate dec declare default defaults deferrable deferred defined definer degree delimiter delimiters dense_rank depth deref derived describe descriptor deterministic diagnostics dictionary disable discard disconnect dispatch dlnewcopy dlpreviouscopy dlurlcomplete dlurlcompleteonly dlurlcompletewrite dlurlpath dlurlpathonly dlurlpathwrite dlurlscheme dlurlserver dlvalue do document domain dynamic dynamic_function dynamic_function_code each element else empty enable encoding encrypted end end-exec end_frame end_partition enforced enum equals escape event every except exception exclude excluding exclusive exec execute exists exp explain expression extension external extract false family fetch file filter final first first_value flag float floor following for force foreign fortran forward found frame_row free freeze fs full function functions fusion g general generated get global go goto grant granted greatest grouping groups handler header hex hierarchy hold hour id identity if ignore ilike immediate immediately immutable implementation implicit import including increment indent index indexes indicator inherit inherits initially inline inner inout input insensitive instance instantiable instead integrity intersect intersection invoker isnull isolation k key key_member key_type label lag language large last last_value lateral lead leading leakproof least left length level library like_regex link listen ln load local localtime localtimestamp location locator lock locked logged lower m map mapping match matched materialized max maxvalue max_cardinality member merge message_length message_octet_length message_text method min minute minvalue mod mode modifies module month more move multiset mumps name names namespace national natural nchar nclob nesting new next nfc nfd nfkc nfkd nil no none normalize normalized nothing notify notnull nowait nth_value ntile null nullable nullif nulls number object occurrences_regex octets octet_length of off offset oids old only open operator option options ordering ordinality others out outer output over overlaps overlay overriding owned owner p pad parallel parameter parameter_mode parameter_name parameter_ordinal_position parameter_specific_catalog parameter_specific_name parameter_specific_schema parser partial partition pascal passing passthrough password percent percentile_cont percentile_disc percent_rank period permission placing plans pli policy portion position position_regex power precedes preceding prepare prepared preserve primary prior privileges procedural procedure program public quote range rank read reads reassign recheck recovery recursive ref references referencing refresh regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy regr_syy reindex relative release rename repeatable replace replica requiring reset respect restart restore restrict restricted result return returned_cardinality returned_length returned_octet_length returned_sqlstate returning returns revoke right role rollback rollup routine routine_catalog routine_name routine_schema row rows row_count row_number rule savepoint scale schema schema_name scope scope_catalog scope_name scope_schema scroll search second section security selective self sensitive sequence sequences serializable server server_name session session_user setof sets share show similar simple size skip snapshot some source space specific specifictype specific_name sql sqlcode sqlerror sqlexception sqlstate sqlwarning sqrt stable standalone start state statement static statistics stddev_pop stddev_samp stdin stdout storage strict strip structure style subclass_origin submultiset substring substring_regex succeeds sum symmetric sysid system system_time system_user t tables tablesample tablespace table_name temp template temporary then ties timezone_hour timezone_minute to token top_level_count trailing transaction transactions_committed transactions_rolled_back transaction_active transform transforms translate translate_regex translation treat trigger trigger_catalog trigger_name trigger_schema trim trim_array true truncate trusted type types uescape unbounded uncommitted under unencrypted unique unknown unlink unlisten unlogged unnamed unnest until untyped upper uri usage user user_defined_type_catalog user_defined_type_code user_defined_type_name user_defined_type_schema using vacuum valid validate validator value value_of varbinary variadic var_pop var_samp verbose version versioning view views volatile when whenever whitespace width_bucket window within work wrapper write xmlagg xmlattributes xmlbinary xmlcast xmlcomment xmlconcat xmldeclaration xmldocument xmlelement xmlexists xmlforest xmliterate xmlnamespaces xmlparse xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltext xmlvalidate year yes loop repeat attach path depends detach zone"),
23 | builtin:a("bigint int8 bigserial serial8 bit varying varbit boolean bool box bytea character char varchar cidr circle date double precision float8 inet integer int int4 interval json jsonb line lseg macaddr macaddr8 money numeric decimal path pg_lsn point polygon real float4 smallint int2 smallserial serial2 serial serial4 text time without zone with timetz timestamp timestamptz tsquery tsvector txid_snapshot uuid xml"),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^\/#@?~]/,dateSQL:a("date time timestamp"),
24 | support:a("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast")});e.defineMIME("text/x-gql",{name:"sql",keywords:a("ancestor and asc by contains desc descendant distinct from group has in is limit offset on order select superset where"),atoms:a("false true"),builtin:a("blob datetime first key __key__ string integer double boolean null"),operatorChars:/^[*+\-%<>!=]/});e.defineMIME("text/x-gpsql",{name:"sql",client:a("source"),keywords:a("abort absolute access action active add admin after aggregate all also alter always analyse analyze and any array as asc assertion assignment asymmetric at authorization backward before begin between bigint binary bit boolean both by cache called cascade cascaded case cast chain char character characteristics check checkpoint class close cluster coalesce codegen collate column comment commit committed concurrency concurrently configuration connection constraint constraints contains content continue conversion copy cost cpu_rate_limit create createdb createexttable createrole createuser cross csv cube current current_catalog current_date current_role current_schema current_time current_timestamp current_user cursor cycle data database day deallocate dec decimal declare decode default defaults deferrable deferred definer delete delimiter delimiters deny desc dictionary disable discard distinct distributed do document domain double drop dxl each else enable encoding encrypted end enum errors escape every except exchange exclude excluding exclusive execute exists explain extension external extract false family fetch fields filespace fill filter first float following for force foreign format forward freeze from full function global grant granted greatest group group_id grouping handler hash having header hold host hour identity if ignore ilike immediate immutable implicit in including inclusive increment index indexes inherit inherits initially inline inner inout input insensitive insert instead int integer intersect interval into invoker is isnull isolation join key language large last leading least left level like limit list listen load local localtime localtimestamp location lock log login mapping master match maxvalue median merge minute minvalue missing mode modifies modify month move name names national natural nchar new newline next no nocreatedb nocreateexttable nocreaterole nocreateuser noinherit nologin none noovercommit nosuperuser not nothing notify notnull nowait null nullif nulls numeric object of off offset oids old on only operator option options or order ordered others out outer over overcommit overlaps overlay owned owner parser partial partition partitions passing password percent percentile_cont percentile_disc placing plans position preceding precision prepare prepared preserve primary prior privileges procedural procedure protocol queue quote randomly range read readable reads real reassign recheck recursive ref references reindex reject relative release rename repeatable replace replica reset resource restart restrict returning returns revoke right role rollback rollup rootpartition row rows rule savepoint scatter schema scroll search second security segment select sequence serializable session session_user set setof sets share show similar simple smallint some split sql stable standalone start statement statistics stdin stdout storage strict strip subpartition subpartitions substring superuser symmetric sysid system table tablespace temp template temporary text then threshold ties time timestamp to trailing transaction treat trigger trim true truncate trusted type unbounded uncommitted unencrypted union unique unknown unlisten until update user using vacuum valid validation validator value values varchar variadic varying verbose version view volatile web when where whitespace window with within without work writable write xml xmlattributes xmlconcat xmlelement xmlexists xmlforest xmlparse xmlpi xmlroot xmlserialize year yes zone"),
25 | builtin:a("bigint int8 bigserial serial8 bit varying varbit boolean bool box bytea character char varchar cidr circle date double precision float float8 inet integer int int4 interval json jsonb line lseg macaddr macaddr8 money numeric decimal path pg_lsn point polygon real float4 smallint int2 smallserial serial2 serial serial4 text time without zone with timetz timestamp timestamptz tsquery tsvector txid_snapshot uuid xml"),atoms:a("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^\/#@?~]/,
26 | dateSQL:a("date time timestamp"),support:a("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast")});e.defineMIME("text/x-sparksql",{name:"sql",keywords:a("add after all alter analyze and anti archive array as asc at between bucket buckets by cache cascade case cast change clear cluster clustered codegen collection column columns comment commit compact compactions compute concatenate cost create cross cube current current_date current_timestamp database databases datata dbproperties defined delete delimited desc describe dfs directories distinct distribute drop else end escaped except exchange exists explain export extended external false fields fileformat first following for format formatted from full function functions global grant group grouping having if ignore import in index indexes inner inpath inputformat insert intersect interval into is items join keys last lateral lazy left like limit lines list load local location lock locks logical macro map minus msck natural no not null nulls of on option options or order out outer outputformat over overwrite partition partitioned partitions percent preceding principals purge range recordreader recordwriter recover reduce refresh regexp rename repair replace reset restrict revoke right rlike role roles rollback rollup row rows schema schemas select semi separated serde serdeproperties set sets show skewed sort sorted start statistics stored stratify struct table tables tablesample tblproperties temp temporary terminated then to touch transaction transactions transform true truncate unarchive unbounded uncache union unlock unset use using values view when where window with"),
27 | builtin:a("tinyint smallint int bigint boolean float double string binary timestamp decimal array map struct uniontype delimited serde sequencefile textfile rcfile inputformat outputformat"),atoms:a("false true null"),operatorChars:/^[*+\-%<>!=~&|^]/,dateSQL:a("date time timestamp"),support:a("ODBCdotTable doubleQuote zerolessFloat")});e.defineMIME("text/x-esper",{name:"sql",client:a("source"),keywords:a("alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit after all and as at asc avedev avg between by case cast coalesce count create current_timestamp day days delete define desc distinct else end escape events every exists false first from full group having hour hours in inner insert instanceof into irstream is istream join last lastweekday left limit like max match_recognize matches median measures metadatasql min minute minutes msec millisecond milliseconds not null offset on or order outer output partition pattern prev prior regexp retain-union retain-intersection right rstream sec second seconds select set some snapshot sql stddev sum then true unidirectional until update variable weekday when where window"),
28 | builtin:{},atoms:a("false true null"),operatorChars:/^[*+\-%<>!=&|^\/#@?~]/,dateSQL:a("time"),support:a("decimallessFloat zerolessFloat binaryNumber hexNumber")})})()});
29 |
--------------------------------------------------------------------------------
/external/sql/AUTHORS:
--------------------------------------------------------------------------------
1 | Ophir LOJKINE (https://github.com/lovasoa)
2 | @kripken
3 | @hankinsoft
4 | @firien
5 | @dinedal
--------------------------------------------------------------------------------
/image/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/image/error.png
--------------------------------------------------------------------------------
/image/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/image/minus.png
--------------------------------------------------------------------------------
/image/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/image/plus.png
--------------------------------------------------------------------------------
/image/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/image/preview.png
--------------------------------------------------------------------------------
/image/update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/image/update.png
--------------------------------------------------------------------------------
/test/ci.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const { Builder, By, Key, until } = require('selenium-webdriver');
4 | const { expect } = require('chai');
5 | const config = require('./config.js').config;
6 | const fs = require('fs');
7 | describe('Web GUI for SQLite', () => {
8 | const driver = new Builder().forBrowser('chrome').build();
9 | it('should go to sqlite page', async () => {
10 | await driver.get(config.dir + '/Web-GUI-for-SQLite.html');
11 | });
12 | it('Upload a database file', async () => {
13 | // db has only one table unittest (CREATE TABLE unittest (a varchar(10), b varchar(10))) with 3 rows
14 | await driver.findElement(By.css('input[id="file-input"]')).sendKeys(config.dir + '/test/test.sqli');
15 | });
16 | it('Load table unittest', async () => {
17 | await (await driver.findElement(By.css('div[data-name="menu-table-unittest"]'))).click();
18 | await driver.sleep(200); // not pretty
19 | expect((await driver.findElements(By.css('table[id="row-results"] img[data-name="deleteRowButton"]'))).length).to.equal(3);
20 | });
21 | it('Delete a row in table unittest', async () => {
22 | var deletButtons = await driver.findElements(By.css('table[id="row-results"] img[data-name="deleteRowButton"]'));
23 | await deletButtons[1].click();
24 | await driver.sleep(200);
25 | driver.switchTo().alert().accept();
26 | await driver.sleep(200);
27 | expect((await driver.findElements(By.css('table[id="row-results"] img[data-name="deleteRowButton"]'))).length).to.equal(2);
28 | });
29 | it('Load a CSV file (contains 3 rows) into unittest', async () => {
30 | await (await driver.findElement(By.css('li a[id="menu-sqlite-importCSV"]'))).click();
31 | await driver.sleep(200);
32 | await driver.findElement(By.css('select[id="ImportSeparator"] option[value=","]')).click();
33 | await driver.findElement(By.css('select[id="ImportHeader"] option[value="yes"]')).click();
34 | await driver.findElement(By.id('ImportNullString')).clear();
35 | await driver.findElement(By.id('ImportNullString')).sendKeys('NULLSPE');// NULLSPE represents a null value
36 | await driver.findElement(By.css('input[id="csv-file-input"]')).sendKeys(config.dir + '/test/test.csv');
37 | await driver.sleep(200);
38 | expect((await driver.findElements(By.css('table[id="row-results"] img[data-name="deleteRowButton"]'))).length).to.equal(5); // 3 - 1 + 3
39 | await (await driver.findElement(By.css('div[id="dialog-table"] button.dialog-close'))).click();
40 | });
41 | it('Execute a select', async () => {
42 | var codeMirrors = await driver.findElements(By.css('div.CodeMirror'));
43 | await driver.executeScript("arguments[0].CodeMirror.setValue(\"Select * from unittest\");", codeMirrors[0]);
44 | await (await driver.findElement(By.id('ExecuteQuery'))).click();
45 | await driver.sleep(200);
46 | var rows = await driver.findElements(By.css('table[id="results"] tbody tr'));
47 | expect(rows.length).to.equal(5);
48 | });
49 | after(async () => driver.quit());
50 | });
51 |
--------------------------------------------------------------------------------
/test/config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const config = {
4 | dir: 'C:/Web-GUI-for-SQLite'
5 | };
6 |
7 | exports.config = config;
8 |
--------------------------------------------------------------------------------
/test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "requires": true,
3 | "lockfileVersion": 1,
4 | "scripts": {
5 | "test": "./node_modules/.bin/mocha ci.js --timeout 10000"
6 | },
7 | "dependencies": {
8 | "chai": "^4.2.0",
9 | "jasmine": {
10 | "integrity": "sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo=",
11 | "requires": {
12 | "glob": "7.1.2",
13 | "jasmine-core": "3.1.0"
14 | },
15 | "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.1.0.tgz",
16 | "version": "3.1.0"
17 | },
18 | "jasmine-core": {
19 | "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=",
20 | "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz",
21 | "version": "3.1.0"
22 | },
23 | "selenium-webdriver": "^4.0.0-alpha.7"
24 | },
25 | "devDependencies": {
26 | "mocha": "^8.0.1"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/test/test.csv:
--------------------------------------------------------------------------------
1 | b
2 | importB1
3 | NULLSPE
4 | importB3
--------------------------------------------------------------------------------
/test/test.sqli:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyrilbois/Web-GUI-for-SQLite/4a6a03f467345664faf6c7969d4c556b0886e34f/test/test.sqli
--------------------------------------------------------------------------------