Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / resources / DatabaseQueryView.js
blob00fc611a10c1f02b6ae8030ba70ebf093fe0972f
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  */
26 /**
27  * @constructor
28  * @extends {WebInspector.VBox}
29  */
30 WebInspector.DatabaseQueryView = function(database)
32     WebInspector.VBox.call(this);
34     this.database = database;
36     this.element.classList.add("storage-view", "query", "monospace");
37     this.element.addEventListener("selectstart", this._selectStart.bind(this), false);
39     this._promptElement = createElement("div");
40     this._promptElement.className = "database-query-prompt";
41     this._promptElement.appendChild(createElement("br"));
42     this._promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
43     this.element.appendChild(this._promptElement);
45     this._prompt = new WebInspector.TextPromptWithHistory(this.completions.bind(this), " ");
46     this._proxyElement = this._prompt.attach(this._promptElement);
48     this.element.addEventListener("click", this._messagesClicked.bind(this), true);
51 WebInspector.DatabaseQueryView.Events = {
52     SchemaUpdated: "SchemaUpdated"
55 WebInspector.DatabaseQueryView.prototype = {
56     /**
57      * @return {!Array.<!WebInspector.ToolbarItem>}
58      */
59     toolbarItems: function()
60     {
61         return [];
62     },
64     _messagesClicked: function()
65     {
66         if (!this._prompt.isCaretInsidePrompt() && this.element.isComponentSelectionCollapsed())
67             this._prompt.moveCaretToEndOfPrompt();
68     },
70     /**
71      * @param {!Element} proxyElement
72      * @param {!Range} wordRange
73      * @param {boolean} force
74      * @param {function(!Array.<string>, number=)} completionsReadyCallback
75      */
76     completions: function(proxyElement, wordRange, force, completionsReadyCallback)
77     {
78         var prefix = wordRange.toString().toLowerCase();
79         if (!prefix)
80             return;
81         var results = [];
83         function accumulateMatches(textArray)
84         {
85             for (var i = 0; i < textArray.length; ++i) {
86                 var text = textArray[i].toLowerCase();
87                 if (text.length < prefix.length)
88                     continue;
89                 if (!text.startsWith(prefix))
90                     continue;
91                 results.push(textArray[i]);
92             }
93         }
95         function tableNamesCallback(tableNames)
96         {
97             accumulateMatches(tableNames.map(function(name) { return name + " "; }));
98             accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
100             completionsReadyCallback(results);
101         }
102         this.database.getTableNames(tableNamesCallback);
103     },
105     _selectStart: function(event)
106     {
107         if (this._selectionTimeout)
108             clearTimeout(this._selectionTimeout);
110         this._prompt.clearAutoComplete();
112         /**
113          * @this {WebInspector.DatabaseQueryView}
114          */
115         function moveBackIfOutside()
116         {
117             delete this._selectionTimeout;
118             if (!this._prompt.isCaretInsidePrompt() && this.element.isComponentSelectionCollapsed())
119                 this._prompt.moveCaretToEndOfPrompt();
120             this._prompt.autoCompleteSoon();
121         }
123         this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
124     },
126     _promptKeyDown: function(event)
127     {
128         if (isEnterKey(event)) {
129             this._enterKeyPressed(event);
130             return;
131         }
132     },
134     _enterKeyPressed: function(event)
135     {
136         event.consume(true);
138         this._prompt.clearAutoComplete(true);
140         var query = this._prompt.text();
141         if (!query.length)
142             return;
144         this._prompt.pushHistoryItem(query);
145         this._prompt.setText("");
147         this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query));
148     },
150     _queryFinished: function(query, columnNames, values)
151     {
152         var dataGrid = WebInspector.SortableDataGrid.create(columnNames, values);
153         var trimmedQuery = query.trim();
155         if (dataGrid) {
156             dataGrid.renderInline();
157             this._appendViewQueryResult(trimmedQuery, dataGrid);
158             dataGrid.autoSizeColumns(5);
159         }
161         if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
162             this.dispatchEventToListeners(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this.database);
163     },
165     _queryError: function(query, errorMessage)
166     {
167         this._appendErrorQueryResult(query, errorMessage);
168     },
170     /**
171      * @param {string} query
172      * @param {!WebInspector.Widget} view
173      */
174     _appendViewQueryResult: function(query, view)
175     {
176         var resultElement = this._appendQueryResult(query);
177         view.show(resultElement);
179         this._promptElement.scrollIntoView(false);
180     },
182     /**
183      * @param {string} query
184      * @param {string} errorText
185      */
186     _appendErrorQueryResult: function(query, errorText)
187     {
188         var resultElement = this._appendQueryResult(query);
189         resultElement.classList.add("error");
190         resultElement.textContent = errorText;
192         this._promptElement.scrollIntoView(false);
193     },
195     _appendQueryResult: function(query)
196     {
197         var element = createElement("div");
198         element.className = "database-user-query";
199         this.element.insertBefore(element, this._proxyElement);
201         var commandTextElement = createElement("span");
202         commandTextElement.className = "database-query-text";
203         commandTextElement.textContent = query;
204         element.appendChild(commandTextElement);
206         var resultElement = createElement("div");
207         resultElement.className = "database-query-result";
208         element.appendChild(resultElement);
209         return resultElement;
210     },
212     __proto__: WebInspector.VBox.prototype