Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / experimental / webtry / res / js / webtry.js
1 /**
2  * Common JS that talks XHR back to the server and runs the code and receives
3  * the results.
4  */
5
6
7 /**
8  * All the functionality is wrapped up in this anonymous closure, but we need
9  * to be told if we are on the workspace page or a normal try page, so the
10  * workspaceName is passed into the closure, it must be set in the global
11  * namespace. If workspaceName is the empty string then we know we aren't
12  * running on a workspace page.
13  *
14  * If we are on a workspace page we also look for a 'history_'
15  * variable in the global namespace which contains the list of tries
16  * that are included in this workspace. That variable is used to
17  * populate the history list.
18  */
19 (function() {
20     function onLoad() {
21       var run             = document.getElementById('run');
22       var permalink       = document.getElementById('permalink');
23       var embed           = document.getElementById('embed');
24       var embedButton     = document.getElementById('embedButton');
25       var code            = document.getElementById('code');
26       var output          = document.getElementById('output');
27       var stdout          = document.getElementById('stdout');
28       var img             = document.getElementById('img');
29       var tryHistory      = document.getElementById('tryHistory');
30       var parser          = new DOMParser();
31       var tryTemplate     = document.getElementById('tryTemplate');
32       var sourcesTemplate = document.getElementById('sourcesTemplate');
33
34       var enableSource   = document.getElementById('enableSource');
35       var selectedSource = document.getElementById('selectedSource');
36       var sourceCode     = document.getElementById('sourceCode');
37       var chooseSource   = document.getElementById('chooseSource');
38       var chooseList     = document.getElementById('chooseList');
39
40       // Id of the source image to use, 0 if no source image is used.
41       var sourceId = 0;
42
43       sourceId = parseInt(enableSource.getAttribute('data-id'));
44       if (sourceId) {
45         sourceSelectByID(sourceId);
46       }
47
48
49       function beginWait() {
50         document.body.classList.add('waiting');
51         run.disabled = true;
52       }
53
54
55       function endWait() {
56         document.body.classList.remove('waiting');
57         run.disabled = false;
58       }
59
60
61       function sourceSelectByID(id) {
62         sourceId = id;
63         if (id > 0) {
64           enableSource.checked = true;
65           selectedSource.innerHTML = '<img with=64 height=64 src="/i/image-'+sourceId+'.png" />';
66           selectedSource.classList.add('show');
67           sourceCode.classList.add('show');
68           chooseSource.classList.remove('show');
69         } else {
70           enableSource.checked = false;
71           selectedSource.classList.remove('show');
72           sourceCode.classList.remove('show');
73         }
74       }
75
76
77       /**
78        * A selection has been made in the choiceList.
79        */
80       function sourceSelect() {
81         sourceSelectByID(parseInt(this.getAttribute('data-id')));
82       }
83
84
85       /**
86        * Callback when the loading of the image sources is complete.
87        *
88        * Fills in the list of images from the data returned.
89        */
90       function sourcesComplete(e) {
91         endWait();
92         // The response is JSON of the form:
93         // [
94         //   {"id": 1},
95         //   {"id": 3},
96         //   ...
97         // ]
98         body = JSON.parse(e.target.response);
99         // Clear out the old list if present.
100         while (chooseList.firstChild) {
101           chooseList.removeChild(chooseList.firstChild);
102         }
103         body.forEach(function(source) {
104          var id = 'i'+source.id;
105          var imgsrc = '/i/image-'+source.id+'.png';
106          var clone = sourcesTemplate.content.cloneNode(true);
107          clone.querySelector('img').src     = imgsrc;
108          clone.querySelector('button').setAttribute('id', id);
109          clone.querySelector('button').setAttribute('data-id', source.id);
110          chooseList.insertBefore(clone, chooseList.firstChild);
111          chooseList.querySelector('#'+id).addEventListener('click', sourceSelect, true);
112         });
113         chooseSource.classList.add('show');
114       }
115
116
117       /**
118        * Toggle the use of a source image, or select a new source image.
119        *
120        * If enabling source images then load the list of available images via
121        * XHR.
122        */
123       function sourceClick(e) {
124         selectedSource.classList.remove('show');
125         sourceCode.classList.remove('show');
126         if (enableSource.checked) {
127           beginWait();
128           var req = new XMLHttpRequest();
129           req.addEventListener('load', sourcesComplete);
130           req.addEventListener('error', xhrError);
131           req.overrideMimeType('application/json');
132           req.open('GET', '/sources/', true);
133           req.send();
134         } else {
135           sourceId = 0;
136         }
137       }
138
139       enableSource.addEventListener('click', sourceClick, true);
140       selectedSource.addEventListener('click', sourceClick, true);
141
142
143       var editor = CodeMirror.fromTextArea(code, {
144         theme: "default",
145         lineNumbers: true,
146         matchBrackets: true,
147         mode: "text/x-c++src",
148         indentUnit: 4,
149       });
150
151       // Match the initial textarea size.
152       editor.setSize(editor.defaultCharWidth() * code.cols,
153                      editor.defaultTextHeight() * code.rows);
154
155
156       /**
157        * Callback when there's an XHR error.
158        * @param e The callback event.
159        */
160       function xhrError(e) {
161         endWait();
162         alert('Something bad happened: ' + e);
163       }
164
165       function clearOutput() {
166         output.textContent = "";
167         if (stdout) {
168           stdout.textContent = "";
169         }
170         embed.style.display='none';
171       }
172
173       /**
174        * Called when an image in the workspace history is clicked.
175        */
176       function historyClick() {
177         beginWait();
178         clearOutput();
179         var req = new XMLHttpRequest();
180         req.addEventListener('load', historyComplete);
181         req.addEventListener('error', xhrError);
182         req.overrideMimeType('application/json');
183         req.open('GET', this.getAttribute('data-try'), true);
184         req.send();
185       }
186
187
188       /**
189        * Callback for when the XHR kicked off in historyClick() returns.
190        */
191       function historyComplete(e) {
192         // The response is JSON of the form:
193         // {
194         //   "hash": "unique id for a try",
195         //   "code": "source code for try"
196         // }
197         endWait();
198         body = JSON.parse(e.target.response);
199         code.value = body.code;
200         editor.setValue(body.code);
201         img.src = '/i/'+body.hash+'.png';
202         sourceSelectByID(body.source);
203         if (permalink) {
204           permalink.href = '/c/' + body.hash;
205         }
206       }
207
208
209       /**
210        * Add the given try image to the history of a workspace.
211        */
212       function addToHistory(hash, imgUrl) {
213         var clone = tryTemplate.content.cloneNode(true);
214         clone.querySelector('img').src = imgUrl;
215         clone.querySelector('.tries').setAttribute('data-try', '/json/' + hash);
216         tryHistory.insertBefore(clone, tryHistory.firstChild);
217         tryHistory.querySelector('.tries').addEventListener('click', historyClick, true);
218       }
219
220
221       /**
222        * Callback for when the XHR returns after attempting to run the code.
223        * @param e The callback event.
224        */
225       function codeComplete(e) {
226         // The response is JSON of the form:
227         // {
228         //   "message": "you had an error...",
229         //   "img": "<base64 encoded image but only on success>"
230         // }
231         //
232         // The img is optional and only appears if there is a valid
233         // image to display.
234         endWait();
235         console.log(e.target.response);
236         body = JSON.parse(e.target.response);
237         output.textContent = body.message;
238         if (stdout) {
239           stdout.textContent = body.stdout;
240         }
241         if (body.hasOwnProperty('img')) {
242           img.src = 'data:image/png;base64,' + body.img;
243         } else {
244           img.src = '';
245         }
246         // Add the image to the history if we are on a workspace page.
247         if (tryHistory) {
248           addToHistory(body.hash, 'data:image/png;base64,' + body.img);
249         } else {
250           window.history.pushState(null, null, '/c/' + body.hash);
251         }
252         if (permalink) {
253           permalink.href = '/c/' + body.hash;
254         }
255         if (embed) {
256           var url = document.URL;
257           url = url.replace('/c/', '/iframe/');
258           embed.value = '<iframe src="' + url + '" width="740" height="550" style="border: solid #00a 5px; border-radius: 5px;"/>'
259         }
260         if (embedButton && embedButton.hasAttribute('disabled')) {
261           embedButton.removeAttribute('disabled');
262         }
263       }
264
265
266       function onSubmitCode() {
267         beginWait();
268         clearOutput();
269         var req = new XMLHttpRequest();
270         req.addEventListener('load', codeComplete);
271         req.addEventListener('error', xhrError);
272         req.overrideMimeType('application/json');
273         req.open('POST', '/', true);
274         req.setRequestHeader('content-type', 'application/json');
275         req.send(JSON.stringify({'code': editor.getValue(), 'name': workspaceName, 'source': sourceId}));
276       }
277       run.addEventListener('click', onSubmitCode);
278
279
280       function onEmbedClick() {
281         embed.style.display='inline';
282       }
283
284       if (embedButton) {
285         embedButton.addEventListener('click', onEmbedClick);
286       }
287
288       // Add the images to the history if we are on a workspace page.
289       if (tryHistory && history_) {
290         for (var i=0; i<history_.length; i++) {
291           addToHistory(history_[i].hash, '/i/'+history_[i].hash+'.png');
292         }
293       }
294     }
295
296     // If loaded via HTML Imports then DOMContentLoaded will be long done.
297     if (document.readyState != "loading") {
298       onLoad();
299     } else {
300       this.addEventListener('load', onLoad);
301     }
302
303 })();