Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / native_client_sdk / src / gonacl_appengine / static / voronoi / example.js
blob8eeb7ee56911c75792eb6b56e71326f69510d8bc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 'use strict';
7 var naclModule = null;
9 /**
10  * A helper function to abbreviate getElementById.
11  *
12  * @param {string} elementId The id to get.
13  * @return {Element}
14  */
15 function $(elementId) {
16   return document.getElementById(elementId);
19 /**
20  * MIME type for PNaCl
21  *
22  * @return {string} MIME type
23  */
24 function PNaClmimeType() {
25   return 'application/x-pnacl';
28 /**
29  * Check if the browser supports PNaCl.
30  *
31  * @return {bool}
32  */
33 function browserSupportsPNaCl() {
34   var mimetype = PNaClmimeType();
35   return navigator.mimeTypes[mimetype] !== undefined;
38 /**
39  * Get the URL for Google Cloud Storage.
40  *
41  * @param {string} name The relative path to the file.
42  * @return {string}
43  */
44 function getDataURL(name) {
45   var revision = '236779';
46   var baseUrl = '//storage.googleapis.com/gonacl/demos/publish/';
47   return baseUrl + revision + '/voronoi/' + name;
50 /**
51  * Create the Native Client <embed> element as a child of the DOM element
52  * named "listener".
53  *
54  * @param {string} name The name of the example.
55  * @param {number} width The width to create the plugin.
56  * @param {number} height The height to create the plugin.
57  * @param {Object} attrs Dictionary of attributes to set on the module.
58  */
59 function createNaClModule(name, width, height, attrs) {
60   var moduleEl = document.createElement('embed');
61   moduleEl.setAttribute('name', 'nacl_module');
62   moduleEl.setAttribute('id', 'nacl_module');
63   moduleEl.setAttribute('width', width);
64   moduleEl.setAttribute('height', height);
65   moduleEl.setAttribute('path', '');
66   moduleEl.setAttribute('src', getDataURL(name + '.nmf'));
67   moduleEl.setAttribute('type', PNaClmimeType());
69   // Add any optional arguments
70   if (attrs) {
71     for (var key in attrs) {
72       moduleEl.setAttribute(key, attrs[key]);
73     }
74   }
76   // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
77   // and a 'message' event listener attached.  This wrapping method is used
78   // instead of attaching the event listeners directly to the <EMBED> element
79   // to ensure that the listeners are active before the NaCl module 'load'
80   // event fires.
81   var listenerDiv = $('listener');
82   listenerDiv.appendChild(moduleEl);
85 /**
86  * Add the default event listeners to the element with id "listener".
87  */
88 function attachDefaultListeners() {
89   var listenerDiv = $('listener');
90   listenerDiv.addEventListener('load', moduleDidLoad, true);
91   listenerDiv.addEventListener('error', moduleLoadError, true);
92   listenerDiv.addEventListener('progress', moduleLoadProgress, true);
93   listenerDiv.addEventListener('crash', handleCrash, true);
94   listenerDiv.addEventListener('message', handleMessage, true);
95   attachListeners();
98 /**
99  * Called when the Browser can not communicate with the Module
101  * This event listener is registered in attachDefaultListeners above.
103  * @param {Object} event
104  */
105 function handleCrash(event) {
106   if (naclModule.exitStatus == -1) {
107     updateStatus('CRASHED');
108   } else {
109     updateStatus('EXITED [' + naclModule.exitStatus + ']');
110   }
114  * Handle a message coming from the NaCl module.
115  * @param {Object} message_event
116  */
117 function handleMessage(event) {
118   if (event.data.message == 'fps') {
119     $('fps').textContent = event.data.value.toFixed(1);
120   }
124  * Called when the NaCl module is loaded.
126  * This event listener is registered in attachDefaultListeners above.
127  */
128 function moduleDidLoad() {
129   var bar = $('progress-bar');
130   bar.style.width = 100;
131   naclModule = $('nacl_module');
132   hideStatus();
133   setThreadCount();
137  * Hide the status field and progress bar.
138  */
139 function hideStatus() {
140   $('loading-cover').style.display = 'none';
145  * Called when the plugin fails to load.
147  * @param {Object} event
148  */
149 function moduleLoadError(event) {
150   updateStatus('Load failed.');
154  * Called when the plugin reports progress events.
156  * @param {Object} event
157  */
158 function moduleLoadProgress(event) {
159   $('progress').style.display = 'block';
161   var loadPercent = 0.0;
162   var bar = $('progress-bar');
164   if (event.lengthComputable && event.total > 0) {
165     loadPercent = event.loaded / event.total * 100.0;
166   } else {
167     // The total length is not yet known.
168     loadPercent = 10;
169   }
170   bar.style.width = loadPercent + "%";
174  * If the element with id 'statusField' exists, then set its HTML to the status
175  * message as well.
177  * @param {string} opt_message The message to set.
178  */
179 function updateStatus(opt_message) {
180   var statusField = $('statusField');
181   if (statusField) {
182     statusField.style.display = 'block';
183     statusField.textContent = opt_message;
184   }
188  * Send the current value of the element threadCount to the NaCl module.
190  * @param {number} threads The number of threads to use to render.
191  */
192 function setThreadCount(threads) {
193   var value = parseInt($('threadCount').value);
194   naclModule.postMessage({'message': 'set_threads',
195                           'value': value});
199  * Add event listeners after the NaCl module has loaded.  These listeners will
200  * forward messages to the NaCl module via postMessage()
201  */
202 function attachListeners() {
203   $('threadCount').addEventListener('change', setThreadCount);
204   $('drawPoints').addEventListener('click',
205     function() {
206       var checked = $('drawPoints').checked;
207       naclModule.postMessage({'message' : 'draw_points',
208                                      'value' : checked});
209     });
210   $('drawInteriors').addEventListener('click',
211     function() {
212       var checked = $('drawInteriors').checked;
213       naclModule.postMessage({'message' : 'draw_interiors',
214                                      'value' : checked});
215     });
216   $('pointRange').addEventListener('change',
217     function() {
218       var value = parseFloat($('pointRange').value);
219       naclModule.postMessage({'message' : 'set_points',
220                                      'value' : value});
221       $('pointCount').textContent = value + ' points';
222     });
226  * Listen for the DOM content to be loaded. This event is fired when parsing of
227  * the page's document has finished.
228  */
229 document.addEventListener('DOMContentLoaded', function() {
230   updateStatus('Loading...');
231   if (!browserSupportsPNaCl()) {
232     updateStatus('Browser does not support PNaCl or PNaCl is disabled');
233   } else if (naclModule == null) {
234     createNaClModule('voronoi', '100%', '100%');
235     attachDefaultListeners();
236   } else {
237     // It's possible that the Native Client module onload event fired
238     // before the page's onload event.  In this case, the status message
239     // will reflect 'SUCCESS', but won't be displayed.  This call will
240     // display the current message.
241     updateStatus('Waiting.');
242   }