diff options
author | gspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-27 23:15:42 +0000 |
---|---|---|
committer | gspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-27 23:15:42 +0000 |
commit | 05b47f7a8c5451f858dc220df0e3a97542edace6 (patch) | |
tree | a2273d619f0625c9d44d40842845ccce2eac1045 /o3d/samples/interactive_logic.js | |
parent | 5cdc8bdb4c847cefe7f4542bd10c9880c2c557a0 (diff) | |
download | chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.zip chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.gz chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.bz2 |
This is the O3D source tree's initial commit to the Chromium tree. It
is not built or referenced at all by the chrome build yet, and doesn't
yet build in it's new home. We'll change that shortly.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17035 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples/interactive_logic.js')
-rw-r--r-- | o3d/samples/interactive_logic.js | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/o3d/samples/interactive_logic.js b/o3d/samples/interactive_logic.js new file mode 100644 index 0000000..e2f9eed --- /dev/null +++ b/o3d/samples/interactive_logic.js @@ -0,0 +1,576 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * @fileoverview This file is the master javascript file for the interactive + * editor/runner for all the simple samples. + * + */ +// For browserFun +// TODO: +// Make it so that you can make the code editing window wider... +// Make it so that you can click links to the documentation of each object +// Add Ping Pong +// Fix the spacing in the editor (when u hit tab) +// Try to see if for the javascript part you can eval line by line so that you +// can output the line number + +var fileTypes = { + 'js' : 'javascript', + 'html' : 'html', + 'php' : 'php' +}; + +function InteractiveSample() { + this.categories = []; + this.codeTitles = []; + this.adjustCodeBoxAmount = 50; + this.selectCode; + this.codeDiv; + this.codeLIs = []; + this.currentCode = new Object(); + this.curI = ''; + this.cleanWindowObj; + + // Assume we're offline until we know that file reading doesn't work + this.online = false; +} + +function sortByCategory(a, b) { + return a.category > b.category; +} + +function sortByName(a, b) { + return a.sampleName > b.sampleName; +} + +function nameToHashName(name) { + var hashName = name.toLowerCase(); + hashName = hashName.replace(/ /g, '_'); + return hashName; +} + +InteractiveSample.prototype.init = function(codeDiv) { + this.codeDiv = codeDiv; + this.createCategories(); + this.addShowHideClicks(); + + // TODO: Sort samples + // codeArray.sort(sortByCategory); + // + // for (var i=0; i < codeArray.length; i++) { + // codeArray[i].samples.sort(sortByName); + // } + + // Gotta set this for the iFrame to know it and change it + // This is specific to O3D because a transparent overlay that is + // under the <object> tag will actually hide the <object> tag + // unless we muck with the zIndex after the <object> loads + window.iframeZindex = '4999'; + + // This is so that we can restore the first level of the window object + // after we run a sample... so samples can get run a lot and not clutter + // the window object. + this.cleanWindowObj = singleLevelKeyCopy(window); +}; + +InteractiveSample.prototype.createCategories = function() { + // codeArray is from interactive_samples.js + this.selectCode = _gel('selectCode'); + + for (var i = 0; i < codeArray.length; i++) { + var container = _cel('span'); + container.className = 'category'; + + var catName = _cel('span'); + + var img = _cel('img'); + img.className = 'collapse'; + img.src = 'interactive_sampler_assets/images/cleardot.gif'; + // addEvent(img, 'click', this.toggleExpand(img), false); + + catName.appendChild(img); + catName.innerHTML += codeArray[i].category; + + container.appendChild(catName); + + var ul = _cel('ul'); + ul.className = 'categoryItems'; + + container.appendChild(ul); + + for (var j = 0; j < codeArray[i].samples.length; j++) { + var item = codeArray[i].samples[j]; + var li = _cel('li'); + + li.innerHTML = item.sampleName; + + this.codeTitles.push(li); + var files = [] + for (var index = 0; index < codeArray[i].samples[j].files.length; + ++index) { + var dirName = ''; + var baseName = codeArray[i].samples[j].files[index]; + var slashIndex = baseName.lastIndexOf('/'); + if (slashIndex >= 0) { + dirName = baseName.substring(0, slashIndex + 1); + baseName = baseName.substring(slashIndex + 1); + } + files[index] = dirName + 'sampler_' + baseName; + } + //var files = codeArray[i].samples[j].files; + addEvent(li, 'click', this.showSample(this, item, files, li)); + + if (i == 0 && j == 0) { + this.showSample(this, item, files, li, true)(); + } + + if (window.location.hash.length > 0) { + var hashName = nameToHashName(item.sampleName); + if (window.location.hash.substring(1) == hashName) { + this.showSample(this, item, files, li)(); + } + } + + this.codeLIs.push(li); + ul.appendChild(li); + } + + this.selectCode.appendChild(container); + this.categories.push(container); + } +}; + +InteractiveSample.prototype.toggleShowHide = function(category, + interactiveSample) { + return function() { + var li = category.nextSibling; + var el = category.childNodes[0]; + if (el.className == 'expand') + el.className = 'collapse'; + else + el.className = 'expand'; + + if (li.style.display == 'none') { + li.style.display = 'block'; + } else { + li.style.display = 'none'; + } + }; +}; + +InteractiveSample.prototype.addShowHideClicks = function() { + for (var i = 0; i < this.categories.length; i++) { + categoryName = this.categories[i].childNodes[0]; + addEvent(categoryName, 'click', this.toggleShowHide(categoryName, this)); + } +}; + +InteractiveSample.prototype.loadLocally = function(relativeUrl, filename, + fileType, + opt_changeCodeMirror) { + // readFile is in utils.js + var data = readFile(relativeUrl); + if (data == null) { + this.online = true; + return false; + } + if (fileType == 'javascript') { + data = this.replaceV8Call(data); + } + if (opt_changeCodeMirror == true) { + this.changeCodeMirror(data, fileType); + } + is_instance.currentCode[filename] = { + code : data + }; + console.log(relativeUrl + ': loaded locally.'); + + return true; +}; + +InteractiveSample.prototype.loadRemotely = function(relativeUrl, filename, + fileType, + opt_changeCodeMirror) { + is_instance = this; + downloadUrl(relativeUrl, function(data, status) { + if (fileType == 'javascript') { + data = this.replaceV8Call(data); + } + if (opt_changeCodeMirror == true) { + is_instance.changeCodeMirror(data, fileType); + } + is_instance.currentCode[filename] = { + code : data + }; + }); +}; + +InteractiveSample.prototype.loadCode = function(filename, + opt_changeCodeMirror) { + // If the code is in the currentCode buffer, then grab it there + // otherwise, load it via XHR + // If opt_changeCodeMirror is specified, load it into the window + + // Get filetype + var filenameSplit = filename.split('.'); + var extension = filenameSplit[filenameSplit.length - 1]; + var fileType = fileTypes[extension.toLowerCase()]; + var inBuffer = (this.currentCode[filename] && + this.currentCode[filename].code) ? true : false; + if (inBuffer && opt_changeCodeMirror == true) { + this.changeCodeMirror(this.currentCode[filename].code, fileType); + } else { + var relativeUrl = filename; + is_instance = this; + + if (!this.online) { + this.loadLocally(relativeUrl, filename, fileType, opt_changeCodeMirror); + } + + if (this.online) { + this.loadRemotely(relativeUrl, filename, fileType, opt_changeCodeMirror); + } + } +}; + +// TODO: can is_instance just be set as is_instance = this above return +// function() +InteractiveSample.prototype.showSample = function(is_instance, codeItem, + files, thisLI, def) { + return function() { + is_instance.refreshInlinePlugin(); + + var codeDiv = is_instance.codeDiv; + var codeLIs = is_instance.codeLIs; + for (var i = 0; i < codeLIs.length; i++) { + codeLIs[i].className = ''; + } + + // turn off the "Run Here" button if this sample should be run in its own + // window. + var runHere = document.getElementById('runHere'); + runHere.style.visibility = codeItem.ownWindow ? 'hidden' : 'visible'; + + // For linking purposes + if (!def) { + window.location.hash = nameToHashName(thisLI.innerHTML); + } + + // Make code selected designate this as selected + thisLI.className = 'selected'; + + is_instance.currentCode = new Object(); + + + // add file names at top + var tab_bar = _gel('tab_bar'); + tab_bar.innerHTML = ''; + + // prototype syntax + files.each(function(file, index) { + + var tabClass = 'lb'; + if (index == 0) { + tabClass = 'db'; + is_instance.loadCode(file, true); + } else { + is_instance.loadCode(file, false); + } + + + var containerDiv = _cel('div'); + containerDiv.className = 'roundedcornr_box'; + addEvent(containerDiv, 'click', is_instance.changeTab(file, is_instance)); + + var html = '<div class="' + tabClass + '_top" ><div></div></div>'; + html += '<div class="' + tabClass + '_roundedcornr_content" >'; + html += file; + html += '</div>'; + + containerDiv.innerHTML = html; + + tab_bar.appendChild(containerDiv); + }); + + // is_instance.loadCode(files[0], textArea); + is_instance.curI = files[0]; + }; +}; + +InteractiveSample.prototype.changeTab = function(i, is_instance) { + return function() { + var siblings = this.parentNode.childNodes; + is_instance.currentCode[is_instance.curI].code = is_instance.getCode(); + + // Swap the colors of the tabs + for (var z = 0; z < siblings.length; z++) { + if (siblings[z].childNodes[1].innerHTML == i) { + siblings[z].childNodes[0].className = 'db_top'; + siblings[z].childNodes[1].className = 'db_roundedcornr_content'; + } else { + siblings[z].childNodes[0].className = 'lb_top'; + siblings[z].childNodes[1].className = 'lb_roundedcornr_content'; + } + } + + is_instance.loadCode(i, true); + is_instance.curI = i; + }; +}; + +InteractiveSample.prototype.increaseCodeBoxHeight = function() { + var curHeight = this.textArea.style.height; + curHeight = curHeight.substr(0, curHeight.indexOf('px')); + var newHeight = parseInt(curHeight) + this.adjustCodeBoxAmount; + newHeight += 'px'; + this.textArea.style.height = newHeight; +}; + +InteractiveSample.prototype.decreaseCodeBoxHeight = function() { + var curHeight = this.textArea.style.height; + curHeight = curHeight.substr(0, curHeight.indexOf('px')); + var newHeight = parseInt(curHeight) - this.adjustCodeBoxAmount; + newHeight += 'px'; + this.textArea.style.height = newHeight; +}; + +InteractiveSample.prototype.replaceV8Call = function(code) { + return code.replace( + /(o3djs.util.setMainEngine[^;\n]+)[;\n]/, + "\n // Can't use V8 in the interactive sampler yet.\n //$1"); +} + +InteractiveSample.prototype.prepareAllCodeRun = function() { + // TODO: Change this so it doesn't rely on the first file being HTML + // TODO: Change this to use REGEX to replace + this.deleteOldWindowStuff(); + + this.refreshInlinePlugin(); + this.currentCode[this.curI].code = this.getCode(); + + var html = ''; + for (var i in this.currentCode) { + if (i.indexOf('.html') != -1) + html = this.currentCode[i].code; + } + var pattern = /<script\s*(type\s*=\s*"[^"]*"\s*)?src\s*=\s*"/g; + var result; + while ((result = pattern.exec(html)) != null) { + var scriptSrc = pattern.lastIndex; + var scriptSrcEnd = html.indexOf('"', scriptSrc); + var script = html.substring(scriptSrc, scriptSrcEnd); + var endScriptLoc = html.indexOf('</script>', scriptSrcEnd) + 9; + var found = false; + for (var z in this.currentCode) { + if (z == script) { + var data = this.replaceV8Call(this.currentCode[z].code); + script = '<script type="text/javascript" charset="utf-8">' + data + + '</script>'; + found = true; + break; + } + } + if (found) { + html = html.substring(0, result.index) + script + + html.substring(endScriptLoc); + } + } + + // console.log(html); + window.codeToRun = html; + + // console.log(html.slice(scriptLoc, endScriptLoc)); + // console.log(html); +}; + +InteractiveSample.prototype.refreshInlinePlugin = function() { + var o3dobject = _gel('o3d'); + o3dparent = o3dobject.parentNode; + o3dparent.removeChild(o3dobject); + + var nO3D = _cel('div'); + nO3D.id = 'o3d'; + nO3D.style.width = '300px'; + nO3D.style.height = '300px'; + nO3D.style.backgroundColor = 'gray'; + + o3dparent.appendChild(nO3D); +}; + +InteractiveSample.prototype.runJS = function() { + // TODO don't assume that we run javascript in any order. Make it so that + // it checks the HTML for which order JS goes in + this.refreshInlinePlugin(); + + // console.log(this.currentCode[0].code.split('\n')); + window.is.startJS(); +}; + +InteractiveSample.prototype.deleteOldWindowStuff = function() { + for (var i in window) { + if (typeof this.cleanWindowObj[i] == 'boolean' && + this.cleanWindowObj[i] == true) { + } else { + window[i] = null; // Delete doesn't remove properties created with var. + delete window[i]; // But just in case we can, we do. + } + } +}; + +InteractiveSample.prototype.startJS = function() { + this.deleteOldWindowStuff(); + var topHolder = _gel('HTMLforInlineJavascript'); + topHolder.innerHTML = ""; + var scriptHolder = document.createElement('div'); + topHolder.appendChild(scriptHolder); + var htmlHolder = document.createElement('div'); + topHolder.appendChild(htmlHolder); + + // NOTE: These are ordered such that no file depends on anything after it. + var forced_includes = [ + "o3djs/base.js", + "o3djs/error.js", + "o3djs/dump.js", + "o3djs/math.js", + "o3djs/serialization.js", + "o3djs/element.js", + "o3djs/shape.js", + "o3djs/rendergraph.js", + "o3djs/test.js", + "o3djs/particles.js", + "o3djs/primitives.js", + "o3djs/quaternions.js", + "o3djs/arcball.js", + "o3djs/event.js", + "o3djs/debug.js", + "o3djs/picking.js", + "o3djs/io.js", + "o3djs/util.js", + "o3djs/effect.js", + "o3djs/material.js", + "o3djs/camera.js", + "o3djs/canvas.js", + "o3djs/pack.js", + "o3djs/scene.js", + "o3djs/loader.js", + "o3djs/simple.js", + "o3djs/fps.js" // If fps isn't last on this list, update the check below. + ]; + + for (var i = 0; i < forced_includes.length; ++i) { + var scr = document.createElement('script'); + scr.type = "text/javascript"; + scr.src = forced_includes[i]; + scriptHolder.appendChild(scr); + } + + this.currentCode[this.curI].code = this.getCode(); + + var sampleJS; + var sampleHTML; + for (var i in this.currentCode) { + if (i.indexOf('.html') != -1) { + // Change the name and id of the object tag before storing the HTML, + // otherwise it will override the inline object we actually want the demo + // to be run in. + sampleHTML = this.currentCode[i].code; + sampleHTML = sampleHTML.replace('id="o3d"', 'id="notouchy"'); + sampleHTML = sampleHTML.replace('id=\'o3d\'', 'id="notouchy"'); + sampleHTML = sampleHTML.replace('name="o3d"', 'name="notouchy"'); + sampleHTML = sampleHTML.replace('name=\'o3d\'', 'name="notouchy"'); + } + if (i.indexOf('.js') != -1) { + sampleJS = this.currentCode[i].code; + } + } + + var intervalId; + var callback = function() { + // fps is the last on the forced_includes list. + if (o3djs != undefined && o3djs.fps) { + clearInterval(intervalId); + intervalId = null; + // TODO Is there any chance that the onload could get called before + // we're done loading the script tag? If so, we'll need to add another + // stage to the callback. + htmlHolder.innerHTML = sampleHTML; + var scr = document.createElement('script'); + scr.type = "text/javascript"; + scr.text = sampleJS; + scriptHolder.appendChild(scr); + try { + if (typeof window.onload == 'function') { + window.onload() + } else if (typeof window.init == 'function') { + window.init(); + } else if (typeof window.initClient == 'function') { + window.initClient(); + } else if (typeof window.createClients == 'function') { + window.createClients(); + } + } catch(e) { + alert(e.message); + } + + _gel('o3d').focus(); + } + } + intervalId = setInterval(callback, 10); +}; + +InteractiveSample.prototype.changeCodeMirror = function(content, lang) { + if (lang == 'javascript') { + window.jsEditor.setCode(content); + window.jsEditor.frame.style.display = 'inline'; + window.htmlEditor.frame.style.display = 'none'; + } else if (lang == 'html') { + window.htmlEditor.setCode(content); + window.htmlEditor.frame.style.display = 'inline'; + window.jsEditor.frame.style.display = 'none'; + } +}; + +InteractiveSample.prototype.getCode = function() { + if (window.htmlEditor.frame.style.display != 'none') { + return window.htmlEditor.getCode(); + } else if (window.jsEditor.frame.style.display != 'none') { + return window.jsEditor.getCode(); + } +}; + +// Todo have the window automatically size to the size of the window + +InteractiveSample.prototype.increaseWidth = function() { + var container = document.getElementById('container'); + var curWidth = container.style.maxWidth = '1800px'; +}; |