diff options
author | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 18:00:44 +0000 |
---|---|---|
committer | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 18:00:44 +0000 |
commit | 167f8adb2e665acb24a5dd4d8fec87a5ac861dc2 (patch) | |
tree | 90dd18720d2005bf194c00c0fae9bc71a6337bd0 /o3d | |
parent | 4c461cbfd2337ffd44fb11a060d6424610595bc1 (diff) | |
download | chromium_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.js | 108 | ||||
-rw-r--r-- | o3d/samples/o3djs/util.js | 179 |
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> + * <script type="text/javascript" id="o3dscript"> + * 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. + * ... + * } + * </script> + * </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(); |