18ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 28ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @fileoverview This file contains miscellaneous basic functionality. 38ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 48ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 58ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 68ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 78ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a DOM element with the given tag name in the document of the 88ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * owner element. 98ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} tagName The name of the tag to create. 118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} owner The intended owner (i.e., parent element) of 128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * the created element. 138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Point} opt_position The top-left corner of the created element. 148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Size} opt_size The size of the created element. 158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Boolean} opt_noAppend Do not append the new element to the owner. 168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Element} The newly created element node. 178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction createElement(tagName, owner, opt_position, opt_size, opt_noAppend) { 198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var element = ownerDocument(owner).createElement(tagName); 208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (opt_position) { 218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen setPosition(element, opt_position); 228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (opt_size) { 248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen setSize(element, opt_size); 258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (owner && !opt_noAppend) { 278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen appendChild(owner, element); 288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return element; 318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a text node with the given value. 358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} value The text to place in the new node. 378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} owner The owner (i.e., parent element) of the new 388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * text node. 398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Text} The newly created text node. 408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction createTextNode(value, owner) { 428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var element = ownerDocument(owner).createTextNode(value); 438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (owner) { 448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen appendChild(owner, element); 458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return element; 478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Returns the document owner of the given element. In particular, 518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * returns window.document if node is null or the browser does not 528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * support ownerDocument. 538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} node The node whose ownerDocument is required. 558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @returns {Document|Null} The owner document or null if unsupported. 568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction ownerDocument(node) { 588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return (node ? node.ownerDocument : null) || document; 598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Wrapper function to create CSS units (pixels) string 638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Number} numPixels Number of pixels, may be floating point. 658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @returns {String} Corresponding CSS units string. 668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction px(numPixels) { 688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return round(numPixels) + "px"; 698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets the left and top of the given element to the given point. 738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} element The dom element to manipulate. 758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Point} point The desired position. 768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction setPosition(element, point) { 788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var style = element.style; 798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen style.position = "absolute"; 808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen style.left = px(point.x); 818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen style.top = px(point.y); 828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets the width and height style attributes to the given size. 868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} element The dom element to manipulate. 888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Size} size The desired size. 898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction setSize(element, size) { 918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var style = element.style; 928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen style.width = px(size.width); 938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen style.height = px(size.height); 948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets display to none. Doing this as a function saves a few bytes for 988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * the 'style.display' property and the 'none' literal. 998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node The dom element to manipulate. 1018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction displayNone(node) { 1038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.style.display = 'none'; 1048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 1078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets display to default. 1088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node The dom element to manipulate. 1108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction displayDefault(node) { 1128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.style.display = ''; 1138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 1168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Appends the given child to the given parent in the DOM 1178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} parent The parent dom element. 1198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} child The new child dom node. 1208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction appendChild(parent, child) { 1228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen parent.appendChild(child); 1238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 1278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Wrapper for the eval() builtin function to evaluate expressions and 1288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * obtain their value. It wraps the expression in parentheses such 1298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * that object literals are really evaluated to objects. Without the 1308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * wrapping, they are evaluated as block, and create syntax 1318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * errors. Also protects against other syntax errors in the eval()ed 1328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * code and returns null if the eval throws an exception. 1338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} expr 1358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Object|Null} 1368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jsEval(expr) { 1388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen try { 1398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return eval('[' + expr + '][0]'); 1408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } catch (e) { 1418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return null; 1428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 1478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Wrapper for the eval() builtin function to execute statements. This 1488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * guards against exceptions thrown, but doesn't return a 1498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * value. Still, mostly for testability, it returns a boolean to 1508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * indicate whether execution was successful. NOTE: 1518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * javascript's eval semantics is murky in that it confounds 1528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * expression evaluation and statement execution into a single 1538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * construct. Cf. jsEval(). 1548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} stmt 1568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Boolean} 1578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jsExec(stmt) { 1598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen try { 1608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen eval(stmt); 1618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 1628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } catch (e) { 1638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 1648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 1698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Wrapper for eval with a context. NOTE: The style guide 1708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * deprecates eval, so this is the exception that proves the 1718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * rule. Notice also that since the value of the expression is 1728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * returned rather than assigned to a local variable, one major 1738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * objection aganist the use of the with() statement, namely that 1748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * properties of the with() target override local variables of the 1758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * same name, is void here. 1768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 1778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} expr 1788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} context 1798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Object|Null} 1808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 1818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jsEvalWith(expr, context) { 1828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen try { 1838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen with (context) { 1848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return eval('[' + expr + '][0]'); 1858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } catch (e) { 1878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return null; 1888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 1898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 1908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 1928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_ELEMENT_NODE = 1; 1938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_ATTRIBUTE_NODE = 2; 1948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_TEXT_NODE = 3; 1958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_CDATA_SECTION_NODE = 4; 1968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_ENTITY_REFERENCE_NODE = 5; 1978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_ENTITY_NODE = 6; 1988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_PROCESSING_INSTRUCTION_NODE = 7; 1998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_COMMENT_NODE = 8; 2008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_DOCUMENT_NODE = 9; 2018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_DOCUMENT_TYPE_NODE = 10; 2028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_DOCUMENT_FRAGMENT_NODE = 11; 2038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar DOM_NOTATION_NODE = 12; 2048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Traverses the element nodes in the DOM tree underneath the given 2078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * node and finds the first node with elemId, or null if there is no such 2088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * element. Traversal is in depth-first order. 2098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * NOTE: The reason this is not combined with the elem() function is 2118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * that the implementations are different. 2128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * elem() is a wrapper for the built-in document.getElementById() function, 2138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * whereas this function performs the traversal itself. 2148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Modifying elem() to take an optional root node is a possibility, 2158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * but the in-built function would perform better than using our own traversal. 2168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Root element of subtree to traverse. 2188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} elemId The id of the element to search for. 2198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Element|Null} The corresponding element, or null if not found. 2208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction nodeGetElementById(node, elemId) { 2228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var c = node.firstChild; c; c = c.nextSibling) { 2238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (c.id == elemId) { 2248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return c; 2258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (c.nodeType == DOM_ELEMENT_NODE) { 2278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var n = arguments.callee.call(this, c, elemId); 2288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (n) { 2298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return n; 2308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 2338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return null; 2348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Get an attribute from the DOM. Simple redirect, exists to compress code. 2398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Element to interrogate. 2418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name Name of parameter to extract. 2428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {String} Resulting attribute. 2438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domGetAttribute(node, name) { 2458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return node.getAttribute(name); 2468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Set an attribute in the DOM. Simple redirect to compress code. 2508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Element to interrogate. 2528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name Name of parameter to set. 2538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} value Set attribute to this value. 2548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domSetAttribute(node, name, value) { 2568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.setAttribute(name, value); 2578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Remove an attribute from the DOM. Simple redirect to compress code. 2618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Element to interrogate. 2638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name Name of parameter to remove. 2648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domRemoveAttribute(node, name) { 2668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.removeAttribute(name); 2678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Clone a node in the DOM. 2718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} node Node to clone. 2738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} Cloned node. 2748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCloneNode(node) { 2768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return node.cloneNode(true); 2778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Return a safe string for the className of a node. 2828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * If className is not a string, returns "". 2838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node DOM element to query. 2858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {String} 2868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domClassName(node) { 2888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return node.className ? "" + node.className : ""; 2898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 2908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 2918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 2928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Adds a class name to the class attribute of the given node. 2938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 2948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node DOM element to modify. 2958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} className Class name to add. 2968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 2978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domAddClass(node, className) { 2988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var name = domClassName(node); 2998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (name) { 3008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var cn = name.split(/\s+/); 3018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var found = false; 3028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(cn); ++i) { 3038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (cn[i] == className) { 3048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen found = true; 3058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen break; 3068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!found) { 3108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen cn.push(className); 3118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.className = cn.join(' '); 3148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 3158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.className = className; 3168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Removes a class name from the class attribute of the given node. 3218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node DOM element to modify. 3238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} className Class name to remove. 3248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domRemoveClass(node, className) { 3268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var c = domClassName(node); 3278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!c || c.indexOf(className) == -1) { 3288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return; 3298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var cn = c.split(/\s+/); 3318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(cn); ++i) { 3328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (cn[i] == className) { 3338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen cn.splice(i--, 1); 3348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen node.className = cn.join(' '); 3378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Checks if a node belongs to a style class. 3418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node DOM element to test. 3438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} className Class name to check for. 3448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Boolean} Node belongs to style class. 3458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domTestClass(node, className) { 3478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var cn = domClassName(node).split(/\s+/); 3488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(cn); ++i) { 3498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (cn[i] == className) { 3508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return true; 3518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 3538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return false; 3548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Inserts a new child before a given sibling. 3588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} newChild Node to insert. 3608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} oldChild Sibling node. 3618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} Reference to new child. 3628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domInsertBefore(newChild, oldChild) { 3648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return oldChild.parentNode.insertBefore(newChild, oldChild); 3658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Appends a new child to the specified (parent) node. 3698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Parent element. 3718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} child Child node to append. 3728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} Newly appended node. 3738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domAppendChild(node, child) { 3758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return node.appendChild(child); 3768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Remove a new child from the specified (parent) node. 3808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} node Parent element. 3828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} child Child node to remove. 3838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} Removed node. 3848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domRemoveChild(node, child) { 3868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return node.removeChild(child); 3878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 3898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 3908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Replaces an old child node with a new child node. 3918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 3928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} newChild New child to append. 3938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} oldChild Old child to remove. 3948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} Replaced node. 3958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 3968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domReplaceChild(newChild, oldChild) { 3978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return oldChild.parentNode.replaceChild(newChild, oldChild); 3988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 3998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Removes a node from the DOM. 4028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Node} node The node to remove. 4048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} The removed node. 4058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domRemoveNode(node) { 4078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return domRemoveChild(node.parentNode, node); 4088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a new text node in the given document. 4128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} text Text composing new text node. 4158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Text} Newly constructed text node. 4168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCreateTextNode(doc, text) { 4188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.createTextNode(text); 4198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a new node in the given document 4238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name Name of new element (i.e. the tag name).. 4268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Element} Newly constructed element. 4278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCreateElement(doc, name) { 4298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.createElement(name); 4308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a new attribute in the given document. 4348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name Name of new attribute. 4378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Attr} Newly constructed attribute. 4388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCreateAttribute(doc, name) { 4408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.createAttribute(name); 4418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a new comment in the given document. 4458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} text Comment text. 4488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Comment} Newly constructed comment. 4498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCreateComment(doc, text) { 4518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.createComment(text); 4528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Creates a document fragment. 4568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {DocumentFragment} Resulting document fragment node. 4598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domCreateDocumentFragment(doc) { 4618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.createDocumentFragment(); 4628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Redirect to document.getElementById 4668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Document} doc Target document. 4688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} id Id of requested node. 4698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Element|Null} Resulting element. 4708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction domGetElementById(doc, id) { 4728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return doc.getElementById(id); 4738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Redirect to window.setInterval 4778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Window} win Target window. 4798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Function} fun Callback function. 4808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Number} time Time in milliseconds. 4818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Object} Contract id. 4828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction windowSetInterval(win, fun, time) { 4848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return win.setInterval(fun, time); 4858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Redirect to window.clearInterval 4898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 4908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Window} win Target window. 4918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {object} id Contract id. 4928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {any} NOTE: Return type unknown? 4938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 4948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction windowClearInterval(win, id) { 4958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return win.clearInterval(id); 4968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 4978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 4988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 4998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Determines whether one node is recursively contained in another. 5008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param parent The parent node. 5018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param child The node to look for in parent. 5028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return parent recursively contains child 5038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction containsNode(parent, child) { 5058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen while (parent != child && child.parentNode) { 5068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen child = child.parentNode; 5078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 5088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return parent == child; 5098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen}; 5108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @fileoverview This file contains javascript utility functions that 5128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * do not depend on anything defined elsewhere. 5138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Returns the value of the length property of the given object. Used 5188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * to reduce compiled code size. 5198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array | String} a The string or array to interrogate. 5218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Number} The value of the length property. 5228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jsLength(a) { 5248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return a.length; 5258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 5268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar min = Math.min; 5288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar max = Math.max; 5298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ceil = Math.ceil; 5308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar floor = Math.floor; 5318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar round = Math.round; 5328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar abs = Math.abs; 5338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Copies all properties from second object to the first. Modifies to. 5368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} to The target object. 5388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} from The source object. 5398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction copyProperties(to, from) { 5418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen foreachin(from, function(p) { 5428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen to[p] = from[p]; 5438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen }); 5448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 5458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Iterates over the array, calling the given function for each 5488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * element. 5498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array} array 5518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Function} fn 5528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction foreach(array, fn) { 5548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var I = jsLength(array); 5558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < I; ++i) { 5568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen fn(array[i], i); 5578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 5588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 5598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Safely iterates over all properties of the given object, calling 5628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * the given function for each property. If opt_all isn't true, uses 5638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * hasOwnProperty() to assure the property is on the object, not on 5648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * its prototype. 5658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} object 5678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Function} fn 5688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Boolean} opt_all If true, also iterates over inherited properties. 5698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction foreachin(object, fn, opt_all) { 5718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i in object) { 5728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (opt_all || !object.hasOwnProperty || object.hasOwnProperty(i)) { 5738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen fn(i, object[i]); 5748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 5758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 5768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 5778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Appends the second array to the first, copying its elements. 5808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Optionally only a slice of the second array is copied. 5818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array} a1 Target array (modified). 5838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array} a2 Source array. 5848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Number} opt_begin Begin of slice of second array (optional). 5858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Number} opt_end End (exclusive) of slice of second array (optional). 5868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 5878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction arrayAppend(a1, a2, opt_begin, opt_end) { 5888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var i0 = opt_begin || 0; 5898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var i1 = opt_end || jsLength(a2); 5908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = i0; i < i1; ++i) { 5918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen a1.push(a2[i]); 5928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 5938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 5948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 5958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 5968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Trim whitespace from begin and end of string. 5978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 5988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @see testStringTrim(); 5998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} str Input string. 6018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {String} Trimmed string. 6028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction stringTrim(str) { 6048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return stringTrimRight(stringTrimLeft(str)); 6058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 6068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Trim whitespace from beginning of string. 6098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @see testStringTrimLeft(); 6118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} str Input string. 6138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {String} Trimmed string. 6148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction stringTrimLeft(str) { 6168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return str.replace(/^\s+/, ""); 6178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 6188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Trim whitespace from end of string. 6218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @see testStringTrimRight(); 6238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} str Input string. 6258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {String} Trimmed string. 6268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction stringTrimRight(str) { 6288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return str.replace(/\s+$/, ""); 6298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 6308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Jscompiler wrapper for parseInt() with base 10. 6338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} s String repersentation of a number. 6358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Number} The integer contained in s, converted on base 10. 6378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction parseInt10(s) { 6398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return parseInt(s, 10); 6408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 6418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @fileoverview A simple formatter to project JavaScript data into 6438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * HTML templates. The template is edited in place. I.e. in order to 6448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * instantiate a template, clone it from the DOM first, and then 6458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * process the cloned template. This allows for updating of templates: 6468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * If the templates is processed again, changed values are merely 6478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * updated. 6488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * NOTE: IE DOM doesn't have importNode(). 6508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * NOTE: The property name "length" must not be used in input 6528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * data, see comment in jstSelect_(). 6538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Names of jstemplate attributes. These attributes are attached to 6588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * normal HTML elements and bind expression context data to the HTML 6598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * fragment that is used as template. 6608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_select = 'jsselect'; 6628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_instance = 'jsinstance'; 6638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_display = 'jsdisplay'; 6648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_values = 'jsvalues'; 6658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_eval = 'jseval'; 6668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_transclude = 'transclude'; 6678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar ATT_content = 'jscontent'; 6688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Names of special variables defined by the jstemplate evaluation 6728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context. These can be used in js expression in jstemplate 6738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * attributes. 6748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar VAR_index = '$index'; 6768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenvar VAR_this = '$this'; 6778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 6808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Context for processing a jstemplate. The context contains a context 6818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * object, whose properties can be referred to in jstemplate 6828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * expressions, and it holds the locally defined variables. 6838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} opt_data The context object. Null if no context. 6858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} opt_parent The parent context, from which local 6878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * variables are inherited. Normally the context object of the parent 6888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context is the object whose property the parent object is. Null for the 6898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context of the root object. 6908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 6918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @constructor 6928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 6938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction JsExprContext(opt_data, opt_parent) { 6948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var me = this; 6958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 6968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen /** 6978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * The local context of the input data in which the jstemplate 6988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * expressions are evaluated. Notice that this is usually an Object, 6998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * but it can also be a scalar value (and then still the expression 7008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * $this can be used to refer to it). Notice this can be a scalar 7018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * value, including undefined. 7028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @type {Object} 7048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.data_ = opt_data; 7068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen /** 7088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * The context for variable definitions in which the jstemplate 7098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * expressions are evaluated. Other than for the local context, 7108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * which replaces the parent context, variable definitions of the 7118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * parent are inherited. The special variable $this points to data_. 7128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @type {Object} 7148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.vars_ = {}; 7168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (opt_parent) { 7178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen copyProperties(me.vars_, opt_parent.vars_); 7188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 7198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen this.vars_[VAR_this] = me.data_; 7208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 7218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 7248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Evaluates the given expression in the context of the current 7258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context object and the current local variables. 7268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} expr A javascript expression. 7288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template DOM node of the template. 7308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return The value of that expression. 7328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7338ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJsExprContext.prototype.jseval = function(expr, template) { 7348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen with (this.vars_) { 7358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen with (this.data_) { 7368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen try { 7378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return (function() { 7388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return eval('[' + expr + '][0]'); 7398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen }).call(template); 7408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } catch (e) { 7418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return null; 7428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 7438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 7448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 7458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 7468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 7498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Clones the current context for a new context object. The cloned 7508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context has the data object as its context object and the current 7518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context as its parent context. It also sets the $index variable to 7528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * the given value. This value usually is the position of the data 7538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * object in a list for which a template is instantiated multiply. 7548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} data The new context object. 7568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Number} index Position of the new context when multiply 7588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * instantiated. (See implementation of jstSelect().) 7598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {JsExprContext} 7618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7628ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJsExprContext.prototype.clone = function(data, index) { 7638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var ret = new JsExprContext(data, this); 7648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen ret.setVariable(VAR_index, index); 7658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (this.resolver_) { 7668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen ret.setSubTemplateResolver(this.resolver_); 7678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 7688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return ret; 7698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 7708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 7738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Binds a local variable to the given value. If set from jstemplate 7748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jsvalue expressions, variable names must start with $, but in the 7758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * API they only have to be valid javascript identifier. 7768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name 7788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Object} value 7808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7818ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJsExprContext.prototype.setVariable = function(name, value) { 7828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen this.vars_[name] = value; 7838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 7848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 7868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 7878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets the function used to resolve the values of the transclude 7888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * attribute into DOM nodes. By default, this is jstGetTemplate(). The 7898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * value set here is inherited by clones of this context. 7908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 7918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Function} resolver The function used to resolve transclude 7928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * ids into a DOM node of a subtemplate. The DOM node returned by this 7938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * function will be inserted into the template instance being 7948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * processed. Thus, the resolver function must instantiate the 7958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * subtemplate as necessary. 7968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 7978ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJsExprContext.prototype.setSubTemplateResolver = function(resolver) { 7988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen this.resolver_ = resolver; 7998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Resolves a sub template from an id. Used to process the transclude 8048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * attribute. If a resolver function was set using 8058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * setSubTemplateResolver(), it will be used, otherwise 8068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jstGetTemplate(). 8078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} id The id of the sub template. 8098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @return {Node} The root DOM node of the sub template, for direct 8118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * insertion into the currently processed template instance. 8128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8138ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJsExprContext.prototype.getSubTemplate = function(id) { 8148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return (this.resolver_ || jstGetTemplate).call(this, id); 8158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * HTML template processor. Data values are bound to HTML templates 8208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * using the attributes transclude, jsselect, jsdisplay, jscontent, 8218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jsvalues. The template is modifed in place. The values of those 8228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * attributes are JavaScript expressions that are evaluated in the 8238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * context of the data object fragment. 8248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {JsExprContext} context Context created from the input data 8268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * object. 8278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template DOM node of the template. This will be 8298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * processed in place. After processing, it will still be a valid 8308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * template that, if processed again with the same data, will remain 8318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * unchanged. 8328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jstProcess(context, template) { 8348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var processor = new JstProcessor(); 8358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen processor.run_([ processor, processor.jstProcess_, context, template ]); 8368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Internal class used by jstemplates to maintain context. 8418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * NOTE: This is necessary to process deep templates in Safari 8428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * which has a relatively shallow stack. 8438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @class 8448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction JstProcessor() { 8468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Runs the state machine, beginning with function "start". 8518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array} start The first function to run, in the form 8538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * [object, method, args ...] 8548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8558ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.run_ = function(start) { 8568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var me = this; 8578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.queue_ = [ start ]; 8598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen while (jsLength(me.queue_)) { 8608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var f = me.queue_.shift(); 8618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen f[1].apply(f[0], f.slice(2)); 8628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 8638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Appends a function to be called later. 8688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Analogous to calling that function on a subsequent line, or a subsequent 8698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * iteration of a loop. 8708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Array} f A function in the form [object, method, args ...] 8728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8738ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.enqueue_ = function(f) { 8748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen this.queue_.push(f); 8758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 8768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 8798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Implements internals of jstProcess. 8808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {JsExprContext} context 8828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 8838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template 8848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 8858ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.jstProcess_ = function(context, template) { 8868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var me = this; 8878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 8888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var transclude = domGetAttribute(template, ATT_transclude); 8898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (transclude) { 8908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var tr = context.getSubTemplate(transclude); 8918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (tr) { 8928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domReplaceChild(tr, template); 8938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_([ me, me.jstProcess_, context, tr ]); 8948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 8958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveNode(template); 8968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 8978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return; 8988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 8998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var select = domGetAttribute(template, ATT_select); 9018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (select) { 9028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.jstSelect_(context, template, select); 9038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return; 9048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var display = domGetAttribute(template, ATT_display); 9078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (display) { 9088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!context.jseval(display, template)) { 9098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayNone(template); 9108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return; 9118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayDefault(template); 9148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var values = domGetAttribute(template, ATT_values); 9188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (values) { 9198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.jstValues_(context, template, values); 9208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var expressions = domGetAttribute(template, ATT_eval); 9238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (expressions) { 9248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen foreach(expressions.split(/\s*;\s*/), function(expression) { 9258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen expression = stringTrim(expression); 9268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (jsLength(expression)) { 9278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen context.jseval(expression, template); 9288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen }); 9308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var content = domGetAttribute(template, ATT_content); 9338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (content) { 9348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.jstContent_(context, template, content); 9358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 9378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var childnodes = []; 9388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(template.childNodes); ++i) { 9398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (template.childNodes[i].nodeType == DOM_ELEMENT_NODE) { 9408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 9418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [ me, me.jstProcess_, context, template.childNodes[i] ]); 9428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 9468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 9498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Implements the jsselect attribute: evalutes the value of the 9508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jsselect attribute in the current context, with the current 9518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * variable bindings (see JsExprContext.jseval()). If the value is an 9528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * array, the current template node is multiplied once for every 9538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * element in the array, with the array element being the context 9548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * object. If the array is empty, or the value is undefined, then the 9558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * current template node is dropped. If the value is not an array, 9568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * then it is just made the context object. 9578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 9588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {JsExprContext} context The current evaluation context. 9598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 9608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template The currently processed node of the template. 9618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 9628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} select The javascript expression to evaluate. 9638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 9648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Function} process The function to continue processing with. 9658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 9668ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.jstSelect_ = function(context, template, select) { 9678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var me = this; 9688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var value = context.jseval(select, template); 9708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveAttribute(template, ATT_select); 9718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var instance = domGetAttribute(template, ATT_instance); 9738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var instance_last = false; 9748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (instance) { 9758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (instance.charAt(0) == '*') { 9768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen instance = parseInt10(instance.substr(1)); 9778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen instance_last = true; 9788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 9798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen instance = parseInt10(instance); 9808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var multiple = (value !== null && 9848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen typeof value == 'object' && 9858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen typeof value.length == 'number'); 9868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var multiple_empty = (multiple && value.length == 0); 9878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (multiple) { 9898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (multiple_empty) { 9908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!instance) { 9918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_select, select); 9928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_instance, '*0'); 9938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayNone(template); 9948ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 9958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveNode(template); 9968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 9978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 9988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 9998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayDefault(template); 10008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (instance === null || instance === "" || instance === undefined || 10018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen (instance_last && instance < jsLength(value) - 1)) { 10028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var templatenodes = []; 10038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var instances_start = instance || 0; 10048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = instances_start + 1; i < jsLength(value); ++i) { 10058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var node = domCloneNode(template); 10068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen templatenodes.push(node); 10078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domInsertBefore(node, template); 10088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen templatenodes.push(template); 10108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(templatenodes); ++i) { 10128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var ii = i + instances_start; 10138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var v = value[ii]; 10148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var t = templatenodes[i]; 10158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_([ me, me.jstProcess_, context.clone(v, ii), t ]); 10178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var instanceStr = (ii == jsLength(value) - 1 ? '*' : '') + ii; 10188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 10198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [ null, postProcessMultiple_, t, select, instanceStr ]); 10208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else if (instance < jsLength(value)) { 10238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var v = value[instance]; 10248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 10268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [me, me.jstProcess_, context.clone(v, instance), template]); 10278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var instanceStr = (instance == jsLength(value) - 1 ? '*' : '') 10288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen + instance; 10298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 10308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [ null, postProcessMultiple_, template, select, instanceStr ]); 10318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 10328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveNode(template); 10338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 10368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (value == null) { 10378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_select, select); 10388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayNone(template); 10398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 10408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 10418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [ me, me.jstProcess_, context.clone(value, 0), template ]); 10428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen me.enqueue_( 10438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen [ null, postProcessSingle_, template, select ]); 10448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 10468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 10478ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 10508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets ATT_select and ATT_instance following recursion to jstProcess. 10518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template The template 10538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} select The jsselect string 10558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} instanceStr The new value for the jsinstance attribute 10578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 10588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction postProcessMultiple_(template, select, instanceStr) { 10598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_select, select); 10608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_instance, instanceStr); 10618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 10628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 10658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Sets ATT_select and makes the element visible following recursion to 10668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jstProcess. 10678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template The template 10698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} select The jsselect string 10718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 10728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction postProcessSingle_(template, select) { 10738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, ATT_select, select); 10748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen displayDefault(template); 10758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 10768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 10788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 10798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Implements the jsvalues attribute: evaluates each of the values and 10808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * assigns them to variables in the current context (if the name 10818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * starts with '$', javascript properties of the current template node 10828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * (if the name starts with '.'), or DOM attributes of the current 10838ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * template node (otherwise). Since DOM attribute values are always 10848ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * strings, the value is coerced to string in the latter case, 10858ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * otherwise it's the uncoerced javascript value. 10868ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10878ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {JsExprContext} context Current evaluation context. 10888ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10898ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template Currently processed template node. 10908ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 10918ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} valuesStr Value of the jsvalues attribute to be 10928ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * processed. 10938ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 10948ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.jstValues_ = function(context, template, valuesStr) { 10958ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var values = valuesStr.split(/\s*;\s*/); 10968ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var i = 0; i < jsLength(values); ++i) { 10978ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var colon = values[i].indexOf(':'); 10988ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (colon < 0) { 10998ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen continue; 11008ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11018ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var label = stringTrim(values[i].substr(0, colon)); 11028ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var value = context.jseval(values[i].substr(colon + 1), template); 11038ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11048ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (label.charAt(0) == '$') { 11058ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen context.setVariable(label, value); 11068ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11078ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else if (label.charAt(0) == '.') { 11088ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var nameSpaceLabel = label.substr(1).split('.'); 11098ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var nameSpaceObject = template; 11108ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var nameSpaceDepth = jsLength(nameSpaceLabel); 11118ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) { 11128ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var jLabel = nameSpaceLabel[j]; 11138ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (!nameSpaceObject[jLabel]) { 11148ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen nameSpaceObject[jLabel] = {}; 11158ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11168ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen nameSpaceObject = nameSpaceObject[jLabel]; 11178ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11188ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value; 11198ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else if (label) { 11208ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (typeof value == 'boolean') { 11218ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (value) { 11228ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, label, label); 11238ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 11248ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveAttribute(template, label); 11258ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11268ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 11278ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domSetAttribute(template, label, '' + value); 11288ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11298ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11308ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11318ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 11328ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11338ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11348ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 11358ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Implements the jscontent attribute. Evalutes the expression in 11368ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * jscontent in the current context and with the current variables, 11378ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * and assigns its string value to the content of the current template 11388ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * node. 11398ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 11408ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {JsExprContext} context Current evaluation context. 11418ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 11428ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {Element} template Currently processed template node. 11438ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 11448ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} content Value of the jscontent attribute to be 11458ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * processed. 11468ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 11478ae428e0fb7feea16d79853f29447469a93bedffKristian MonsenJstProcessor.prototype.jstContent_ = function(context, template, content) { 11488ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var value = '' + context.jseval(content, template); 11498ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (template.innerHTML == value) { 11508ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return; 11518ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11528ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen while (template.firstChild) { 11538ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveNode(template.firstChild); 11548ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11558ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var t = domCreateTextNode(ownerDocument(template), value); 11568ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domAppendChild(template, t); 11578ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 11588ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11598ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11608ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen/** 11618ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * Helps to implement the transclude attribute, and is the initial 11628ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * call to get hold of a template from its ID. 11638ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 11648ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @param {String} name The ID of the HTML element used as template. 11658ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * 11668ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * @returns {Element} The DOM node of the template. (Only element 11678ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen * nodes can be found by ID, hence it's a Element.) 11688ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen */ 11698ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenfunction jstGetTemplate(name) { 11708ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var section = domGetElementById(document, name); 11718ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen if (section) { 11728ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen var ret = domCloneNode(section); 11738ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen domRemoveAttribute(ret, 'id'); 11748ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return ret; 11758ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } else { 11768ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen return null; 11778ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen } 11788ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen} 11798ae428e0fb7feea16d79853f29447469a93bedffKristian Monsen 11808ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenwindow['jstGetTemplate'] = jstGetTemplate; 11818ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenwindow['jstProcess'] = jstProcess; 11828ae428e0fb7feea16d79853f29447469a93bedffKristian Monsenwindow['JsExprContext'] = JsExprContext; 1183