summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-21 18:00:44 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-21 18:00:44 +0000
commit167f8adb2e665acb24a5dd4d8fec87a5ac861dc2 (patch)
tree90dd18720d2005bf194c00c0fae9bc71a6337bd0 /o3d
parent4c461cbfd2337ffd44fb11a060d6424610595bc1 (diff)
downloadchromium_src-167f8adb2e665acb24a5dd4d8fec87a5ac861dc2.zip
chromium_src-167f8adb2e665acb24a5dd4d8fec87a5ac861dc2.tar.gz
chromium_src-167f8adb2e665acb24a5dd4d8fec87a5ac861dc2.tar.bz2
Added o3djs.util.getElementsByTagAndId and
o3djs.util.getO3DContainerElements which encasplulates the way we were finding elements to make O3D tags in. I also put an example of how to make your own failure callback in the docs. This also brought up a known issue in the doc generator so that fix is included here. Review URL: http://codereview.chromium.org/173178 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23976 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/documentation/jsdoc-toolkit-templates/publish.js108
-rw-r--r--o3d/samples/o3djs/util.js179
2 files changed, 213 insertions, 74 deletions
diff --git a/o3d/documentation/jsdoc-toolkit-templates/publish.js b/o3d/documentation/jsdoc-toolkit-templates/publish.js
index cf1800c..9fe8736 100644
--- a/o3d/documentation/jsdoc-toolkit-templates/publish.js
+++ b/o3d/documentation/jsdoc-toolkit-templates/publish.js
@@ -64,6 +64,20 @@ var g_baseURL;
var g_topURL;
var g_templates = [];
var g_o3dPropertyRE = /^(\w+)\s+(\w+)\s+/;
+var g_startContainerRE = /^(?:function\(|!function\(|[\(<{[])/;
+var g_containerRE = /function\(|!function\(|[\(<{[]/;
+var g_openCloseMap = {
+ 'function(': ')',
+ '!function(': ')',
+ '(': ')',
+ '<': '>',
+ '[': ']',
+ '{': '}'};
+var g_closeMap = {
+ ')': true,
+ '>': true,
+ ']': true,
+ '}': true};
/**
* Called automatically by JsDoc Toolkit.
@@ -627,29 +641,18 @@ function reportUnknownType(place, type) {
* @return {number} Index of closing character or (-1) if not found.
*/
function getIndexOfClosingCharacter(str, startIndex) {
- var openCloseMap = {
- '(': ')',
- '<': '>',
- '[': ']',
- '{': '}'};
- var closeMap = {
- ')': true,
- '>': true,
- ']': true,
- '}': true,
- };
var stack = [];
- if (!openCloseMap[str[startIndex]]) {
+ if (!g_openCloseMap[str[startIndex]]) {
throw 'startIndex does not point to opening character.';
}
var endIndex = str.length;
while (startIndex < endIndex) {
var c = str[startIndex];
- var closing = openCloseMap[c];
+ var closing = g_openCloseMap[c];
if (closing) {
stack.unshift(closing);
} else {
- closing = closeMap[c];
+ closing = g_closeMap[c];
if (closing) {
var expect = stack.shift()
if (c != expect) {
@@ -762,6 +765,8 @@ function linkifySingleType(place, type) {
var output = '';
var argsStr = type.substring(9, closingParen);
if (argsStr) {
+ // TODO(gman): This needs to split taking parens, brackets and angle
+ // brackets into account.
var args = argsStr.split(/ *, */);
for (var ii = 0; ii < args.length; ++ii) {
if (ii > 0) {
@@ -832,30 +837,85 @@ function linkifySingleType(place, type) {
}
/**
+ * Splits a string by containers. A string like "ab(cd,ef)gh" will
+ * be returned as ['ab', '(cd,ef)', 'gh']
+ * @param {string} str String to split.
+ * @return {!Array.<string>} The split string parts.
+ */
+function splitByContainers(str) {
+ var parts = [];
+ for (;;) {
+ var match = str.match(g_containerRE);
+ if (!match) {
+ if (str.length > 0) {
+ parts.push(str);
+ }
+ return parts;
+ }
+ var startIndex = str.indexOf(match);
+ if (startIndex != 0) {
+ parts.push(str.substring(0, startIndex));
+ }
+ var endIndex = getIndexOfClosingCharacter(
+ str, startIndex + match.toString().length - 1);
+ if (endIndex < 0) {
+ throw 'no closing character for "' + str[startIndex] + '" in "' + str +
+ '"';
+ }
+ var piece = str.substring(startIndex, endIndex + 1);
+ parts.push(piece);
+ str = str.substring(endIndex + 1);
+ }
+}
+
+/**
* Fix function specs.
* The jsdoctoolkit wrongly converts ',' to | as in 'function(a, b)' to
* 'function(a|b)' and '{id1: type1, id2: type2}' to '{id1: type1|id2: type2}'
* so we need to put those back here (or fix jsdoctoolkit, the proper solution).
+ * Worse, we have to distinguish between 'function(a|b)' and '(a|b)'. The former
+ * needs to become 'function(a, b)' while the later needs to stay the same.
+ *
* @param {string} str JSDOC type specification string .
+ * @param {boolean} opt_paren True if we are inside a paren.
* @return {string} str with '|' converted back to ', ' unless the specification
* starts with '(' and ends with ')'. That's not a very good check beacuse
* you could 'function((string|number)) and this would fail to do the right
* thing.
- *
*/
-function fixSpecCommas(str) {
- // TODO: This is really a complete hack and we should fix the
- // jsdoctoolkit.
- if (startsWith(str, '(') && endsWith(str, ')')) {
- return str;
+function fixSpecCommas(str, opt_paren) {
+ var start = str.match(g_startContainerRE);
+ if (start) {
+ var startStr = start.toString();
+ var closing = g_openCloseMap[startStr];
+ if (closing) {
+ var lastChar = str[str.length - 1];
+ if (lastChar == closing) {
+ var middle = str.substring(startStr.length, str.length - 1);
+ return startStr +
+ fixSpecCommas(middle, startStr === '(') +
+ lastChar;
+ }
+ }
+ }
+
+ if (str.match(g_containerRE)) {
+ var parts = splitByContainers(str);
+ for (var ii = 0; ii < parts.length; ++ii) {
+ parts[ii] = fixSpecCommas(parts[ii], opt_paren);
+ }
+ return parts.join('');
} else {
+ if (opt_paren) {
+ return str;
+ }
return str.replace(/\|/g, ', ');
}
}
/**
* Converts a JSDOC type specification into html links. For example
- * '(!o3djs.math.Vector3|!O3D.math.Vector4)' would change to
+ * '(!o3djs.math.Vector3|!o3djs.math.Vector4)' would change to
* '(!<a href="??">o3djs.math.Vector3</a>
* |!<a href="??">o3djs.math.Vector4</a>)'.
* @param {string} place Use to print error message if type not found.
@@ -865,7 +925,11 @@ function fixSpecCommas(str) {
function linkifyTypeSpec(place, str) {
var output = '';
if (str) {
- var fixed = fixSpecCommas(str);
+ try {
+ var fixed = fixSpecCommas(str);
+ } catch (e) {
+ generatePlaceError(place, e);
+ }
// TODO: needs to split outside of parens and angle brackets.
if (startsWith(fixed, '(') && endsWith(fixed, ')')) {
var types = fixed.substring(1, fixed.length - 1).split('|');
diff --git a/o3d/samples/o3djs/util.js b/o3d/samples/o3djs/util.js
index 6df3e93..7a956d4 100644
--- a/o3d/samples/o3djs/util.js
+++ b/o3d/samples/o3djs/util.js
@@ -63,6 +63,18 @@ o3djs.util.PLUGIN_NAME = 'O3D Plugin';
o3djs.util.REQUIRED_VERSION = '0.1.40.0';
/**
+ * The width an O3D must be to put a failure message inside
+ * @type {number}
+ */
+o3djs.util.MINIMUM_WIDTH_FOR_MESSAGE = 200;
+
+/**
+ * The height an O3D must be to put a failure message inside
+ * @type {number}
+ */
+o3djs.util.MINIMUM_HEIGHT_FOR_MESSAGE = 200;
+
+/**
* A URL at which to download the client.
* @type {string}
*/
@@ -326,6 +338,36 @@ o3djs.util.requiredVersionAvailable = function(requiredVersion) {
};
/**
+ * Gets all the elements of a certain tag that have a certain id.
+ * @param {string} tag The tag to look for. (eg. 'div').
+ * @param {string} id The id to look for. This can be a regular expression.
+ * @return {!Array.<!Element>} An array of the elements found.
+ */
+o3djs.util.getElementsByTagAndId = function(tag, id) {
+ var elements = [];
+ var allElements = document.getElementsByTagName(tag);
+ for (var ee = 0; ee < allElements.length; ++ee) {
+ var element = allElements[ee];
+ if (element.id && element.id.match(id)) {
+ elements.push(element);
+ }
+ }
+ return elements;
+};
+
+/**
+ * Gets all the Elements that contain or would contain O3D plugin objects.
+ * @param {string} opt_id The id to look for. This can be a regular
+ * expression. The default is "^o3d".
+ * @param {string} opt_tag The type of tag to look for. The default is "div".
+ */
+o3djs.util.getO3DContainerElements = function(opt_id, opt_tag) {
+ var tag = opt_tag || 'div';
+ var id = opt_id || '^o3d';
+ return o3djs.util.getElementsByTagAndId(tag, id);
+}
+
+/**
* Offers the user the option to download the plugin.
*
* Finds all divs with the id "^o3d" and inserts a message and link
@@ -337,10 +379,8 @@ o3djs.util.requiredVersionAvailable = function(requiredVersion) {
* @param {string} opt_tag The type of tag to look for. The default is "div".
*/
o3djs.util.offerPlugin = function(opt_id, opt_tag) {
- var tag = opt_tag || 'div';
- var id = opt_id || '^o3d';
var havePlugin = o3djs.util.requiredVersionAvailable('');
- var elements = document.getElementsByTagName(tag);
+ var elements = o3djs.util.getO3DContainerElements(opt_id, opt_tag);
var addedMessage = false;
// TODO: This needs to be localized OR we could insert a html like
// <script src="http://google.com/o3d_plugin_dl"></script>
@@ -359,14 +399,12 @@ o3djs.util.offerPlugin = function(opt_id, opt_tag) {
'</div>'
for (var ee = 0; ee < elements.length; ++ee) {
var element = elements[ee];
- if (element.id && element.id.match(id)) {
- if (element.clientWidth >= 200 &&
- element.clientHeight >= 200 &&
- element.style.display.toLowerCase() != 'none' &&
- element.style.visibility.toLowerCase() != 'hidden') {
- addedMessage = true;
- element.innerHTML = message;
- }
+ if (element.clientWidth >= o3djs.util.MINIMUM_WIDTH_FOR_MESSAGE &&
+ element.clientHeight >= o3djs.util.MINIMUM_HEIGHT_FOR_MESSAGE &&
+ element.style.display.toLowerCase() != 'none' &&
+ element.style.visibility.toLowerCase() != 'hidden') {
+ addedMessage = true;
+ element.innerHTML = message;
}
}
if (!addedMessage) {
@@ -392,9 +430,7 @@ o3djs.util.offerPlugin = function(opt_id, opt_tag) {
* @param {string} opt_tag The type of tag to look for. The default is "div".
*/
o3djs.util.informNoGraphics = function(initStatus, error, opt_id, opt_tag) {
- var tag = opt_tag || 'div';
- var id = opt_id || '^o3d';
- var elements = document.getElementsByTagName(tag);
+ var elements = o3djs.util.getO3DContainerElements(opt_id, opt_tag);
var addedMessage = false;
var subMessage;
var message;
@@ -453,14 +489,12 @@ o3djs.util.informNoGraphics = function(initStatus, error, opt_id, opt_tag) {
}
for (var ee = 0; ee < elements.length; ++ee) {
var element = elements[ee];
- if (element.id && element.id.match(id)) {
- if (element.clientWidth >= 200 &&
- element.clientHeight >= 200 &&
- element.style.display.toLowerCase() != 'none' &&
- element.style.visibility.toLowerCase() != 'hidden') {
- addedMessage = true;
- element.innerHTML = message;
- }
+ if (element.clientWidth >= o3djs.util.MINIMUM_WIDTH_FOR_MESSAGE &&
+ element.clientHeight >= o3djs.util.MINIMUM_HEIGHT_FOR_MESSAGE &&
+ element.style.display.toLowerCase() != 'none' &&
+ element.style.visibility.toLowerCase() != 'hidden') {
+ addedMessage = true;
+ element.innerHTML = message;
}
}
if (!addedMessage) {
@@ -708,9 +742,9 @@ o3djs.util.getScriptTagText_ = function() {
};
/**
- * Creates a client element. In other words it creates an <OBJECT> tag for
- * o3d. Note that the browser may not have initialized the plugin before
- * returning.
+ * Creates a client element. In other words it creates an <OBJECT> tag for o3d.
+ * <b>Note that the browser may not have initialized the plugin before
+ * returning.</b>
* @param {!Element} element The DOM element under which the client element
* will be appended.
* @param {string} opt_features A comma separated list of the
@@ -782,6 +816,47 @@ o3djs.util.createClient = function(element, opt_features, opt_requestVersion) {
* This allows you to specify different features per area. Otherwise you can
* request features as an argument to this function.
*
+ * Normally this function handles failure for you but if you want to handle
+ * failure in your own way you can supply a failure callback. Here is an example
+ * of using this function with your own failure callback.
+ *
+ * <pre>
+ * &lt;script type="text/javascript" id="o3dscript"&gt;
+ * o3djs.require('o3djs.util');
+ *
+ * window.onload = init;
+ *
+ * function init() {
+ * o3djs.util.makeClients(onSuccess, '', undefined, onFailure);
+ * }
+ *
+ * function onFailure(initStatus, error, id, tag) {
+ * // Get a list of the elements that would have had an O3D plugin object
+ * // inserted if it had succeed.
+ * var elements = o3djs.util.getO3DContainerElements(id, tag);
+ *
+ * switch (initStatus) {
+ * case o3djs.util.rendererInitStatus.NO_PLUGIN:
+ * // Tell the user there is no plugin
+ * ...
+ * break;
+ * case o3djs.util.rendererInitStatus.OUT_OF_RESOURCES:
+ * case o3djs.util.rendererInitStatus.GPU_NOT_UP_TO_SPEC:,
+ * case o3djs.util.rendererInitStatus.INITIALIZATION_ERROR:
+ * default:
+ * // Tell the user there are other issues
+ * ...
+ * break;
+ * }
+ * }
+ *
+ * function onSuccess(o3dElementsArray) {
+ * // Run your app.
+ * ...
+ * }
+ * &lt;/script&gt;
+ * </pre>
+ *
* @param {!function(Array.<!Element>): void} callback Function to call when
* client objects have been created.
* @param {string} opt_features A comma separated list of the
@@ -801,14 +876,17 @@ o3djs.util.createClient = function(element, opt_features, opt_requestVersion) {
* "2.4" = require major version 2, minor version 4. If no string is
* passed in the version of the needed by this version of the javascript
* libraries will be created.
- * @param {!function(!o3d.Renderer.InitStatus, string, string, string): void}
- * opt_failureCallback Function to call if the plugin does not exist, if the
- * required version is not installed, or if for some other reason the plugin
- * can not start. If this function is not specified or is null the default
- * behavior of leading the user to the download page will be provided.
+ * @param {!function(!o3d.Renderer.InitStatus, string, (string|undefined),
+ * (string|undefined)): void} opt_failureCallback Function to call if the
+ * plugin does not exist, if the required version is not installed, or if
+ * for some other reason the plugin can not start. If this function is not
+ * specified or is null the default behavior of leading the user to the
+ * download page will be provided. See o3djs.util.informPluginFailure for an
+ * example of this type of callback.
* @param {string} opt_id The id to look for. This can be a regular
* expression. The default is "^o3d".
* @param {string} opt_tag The type of tag to look for. The default is "div".
+ * @see o3djs.util.informPluginFailure
*/
o3djs.util.makeClients = function(callback,
opt_features,
@@ -816,38 +894,35 @@ o3djs.util.makeClients = function(callback,
opt_failureCallback,
opt_id,
opt_tag) {
- var tag = opt_tag || 'div';
- var id = opt_id || '^o3d';
opt_failureCallback = opt_failureCallback || o3djs.util.informPluginFailure;
opt_requiredVersion = opt_requiredVersion || o3djs.util.REQUIRED_VERSION;
if (!o3djs.util.requiredVersionAvailable(opt_requiredVersion)) {
- opt_failureCallback(o3djs.util.rendererInitStatus.NO_PLUGIN, '', id, tag);
+ opt_failureCallback(o3djs.util.rendererInitStatus.NO_PLUGIN, '',
+ opt_id, opt_tag);
} else {
var clientElements = [];
- var elements = document.getElementsByTagName(tag);
+ var elements = o3djs.util.getO3DContainerElements(opt_id, opt_tag);
var mainClientElement = null;
for (var ee = 0; ee < elements.length; ++ee) {
var element = elements[ee];
- if (element.id && element.id.match(id)) {
- var features = opt_features;
- if (!features) {
- var o3d_features = element.getAttribute('o3d_features');
- if (o3d_features) {
- features = o3d_features;
- } else {
- features = '';
- }
+ var features = opt_features;
+ if (!features) {
+ var o3d_features = element.getAttribute('o3d_features');
+ if (o3d_features) {
+ features = o3d_features;
+ } else {
+ features = '';
}
+ }
- var objElem = o3djs.util.createClient(element, features);
- clientElements.push(objElem);
+ var objElem = o3djs.util.createClient(element, features);
+ clientElements.push(objElem);
- // If the callback is to be invoked in an embedded JavaScript engine,
- // one element must be identified with the id 'o3d'. This callback
- // will be invoked in the element identified as such.
- if (element.id === 'o3d') {
- mainClientElement = objElem;
- }
+ // If the callback is to be invoked in an embedded JavaScript engine,
+ // one element must be identified with the id 'o3d'. This callback
+ // will be invoked in the element identified as such.
+ if (element.id === 'o3d') {
+ mainClientElement = objElem;
}
}
@@ -901,7 +976,7 @@ o3djs.util.makeClients = function(callback,
var clientElement = clientElements[cc];
clientElement.parentNode.removeChild(clientElement);
}
- opt_failureCallback(initStatus, error, id, tag);
+ opt_failureCallback(initStatus, error, opt_id, opt_tag);
} else {
o3djs.base.snapshotProvidedNamespaces();