initial import
[vuplus_webkit] / Source / WebCore / inspector / front-end / DatabaseQueryView.js
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.DatabaseQueryView = function(database)
27 {
28     WebInspector.View.call(this);
29
30     this.database = database;
31
32     this.element.addStyleClass("storage-view");
33     this.element.addStyleClass("query");
34     this.element.addStyleClass("monospace");
35     this.element.tabIndex = 0;
36
37     this.element.addEventListener("selectstart", this._selectStart.bind(this), false);
38
39     this.promptElement = document.createElement("div");
40     this.promptElement.className = "database-query-prompt";
41     this.promptElement.appendChild(document.createElement("br"));
42     this.promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
43     this.element.appendChild(this.promptElement);
44
45     this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " ");
46 }
47
48 WebInspector.DatabaseQueryView.prototype = {
49     show: function(parentElement)
50     {
51         WebInspector.View.prototype.show.call(this, parentElement);
52
53         function moveBackIfOutside()
54         {
55             if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
56                 this.prompt.moveCaretToEndOfPrompt();
57         }
58
59         setTimeout(moveBackIfOutside.bind(this), 0);
60     },
61
62     completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
63     {
64         var prefix = wordRange.toString().toLowerCase();
65         if (!prefix.length)
66             return;
67
68         var results = [];
69
70         function accumulateMatches(textArray)
71         {
72             if (bestMatchOnly && results.length)
73                 return;
74             for (var i = 0; i < textArray.length; ++i) {
75                 var text = textArray[i].toLowerCase();
76                 if (text.length < prefix.length)
77                     continue;
78                 if (text.indexOf(prefix) !== 0)
79                     continue;
80                 results.push(textArray[i]);
81                 if (bestMatchOnly)
82                     return;
83             }
84         }
85
86         function tableNamesCallback(tableNames)
87         {
88             accumulateMatches(tableNames.map(function(name) { return name + " " }));
89             accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
90
91             completionsReadyCallback(results);
92         }
93         this.database.getTableNames(tableNamesCallback);
94     },
95
96     _promptKeyDown: function(event)
97     {
98         if (isEnterKey(event)) {
99             this._enterKeyPressed(event);
100             return;
101         }
102     },
103
104     _selectStart: function(event)
105     {
106         if (this._selectionTimeout)
107             clearTimeout(this._selectionTimeout);
108
109         this.prompt.clearAutoComplete();
110
111         function moveBackIfOutside()
112         {
113             delete this._selectionTimeout;
114             if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
115                 this.prompt.moveCaretToEndOfPrompt();
116             this.prompt.autoCompleteSoon();
117         }
118
119         this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
120     },
121
122     _enterKeyPressed: function(event)
123     {
124         event.preventDefault();
125         event.stopPropagation();
126
127         this.prompt.clearAutoComplete(true);
128
129         var query = this.prompt.text;
130         if (!query.length)
131             return;
132
133         this.prompt.history.push(query);
134         this.prompt.historyOffset = 0;
135         this.prompt.text = "";
136
137         this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query));
138     },
139
140     _queryFinished: function(query, columnNames, values)
141     {
142         var dataGrid = WebInspector.panels.resources.dataGridForResult(columnNames, values);
143         var trimmedQuery = query.trim();
144
145         if (dataGrid) {
146             dataGrid.element.addStyleClass("inline");
147             this._appendQueryResult(trimmedQuery, dataGrid.element);
148             dataGrid.autoSizeColumns(5);
149         }
150
151         if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
152             WebInspector.panels.resources.updateDatabaseTables(this.database);
153     },
154
155     _queryError: function(query, error)
156     {
157         if (error.message)
158             var message = error.message;
159         else if (error.code == 2)
160             var message = WebInspector.UIString("Database no longer has expected version.");
161         else
162             var message = WebInspector.UIString("An unexpected error %s occurred.", error.code);
163
164         this._appendQueryResult(query, message, "error");
165     },
166
167     _appendQueryResult: function(query, result, resultClassName)
168     {
169         var element = document.createElement("div");
170         element.className = "database-user-query";
171
172         var commandTextElement = document.createElement("span");
173         commandTextElement.className = "database-query-text";
174         commandTextElement.textContent = query;
175         element.appendChild(commandTextElement);
176
177         var resultElement = document.createElement("div");
178         resultElement.className = "database-query-result";
179
180         if (resultClassName)
181             resultElement.addStyleClass(resultClassName);
182
183         if (typeof result === "string" || result instanceof String)
184             resultElement.textContent = result;
185         else if (result && result.nodeName)
186             resultElement.appendChild(result);
187
188         if (resultElement.childNodes.length)
189             element.appendChild(resultElement);
190
191         this.element.insertBefore(element, this.promptElement);
192         this.promptElement.scrollIntoView(false);
193     }
194 }
195
196 WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype;