http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/733b57dd/odatajs/demo/scripts/datajs-1.1.2.js ---------------------------------------------------------------------- diff --git a/odatajs/demo/scripts/datajs-1.1.2.js b/odatajs/demo/scripts/datajs-1.1.2.js deleted file mode 100644 index 5040efc..0000000 --- a/odatajs/demo/scripts/datajs-1.1.2.js +++ /dev/null @@ -1,10577 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// odatajs.js - -(function (window, undefined) { - - var datajs = window.odatajs || {}; - var odata = window.OData || {}; - - // AMD support - if (typeof define === 'function' && define.amd) { - define('datajs', datajs); - define('OData', odata); - } else { - window.odatajs = datajs; - window.OData = odata; - } - - odatajs.version = { - major: 1, - minor: 1, - build: 1 - }; - - - var activeXObject = function (progId) { - /// <summary>Creates a new ActiveXObject from the given progId.</summary> - /// <param name="progId" type="String" mayBeNull="false" optional="false"> - /// ProgId string of the desired ActiveXObject. - /// </param> - /// <remarks> - /// This function throws whatever exception might occur during the creation - /// of the ActiveXObject. - /// </remarks> - /// <returns type="Object"> - /// The ActiveXObject instance. Null if ActiveX is not supported by the - /// browser. - /// </returns> - if (window.ActiveXObject) { - return new window.ActiveXObject(progId); - } - return null; - }; - - var assigned = function (value) { - /// <summary>Checks whether the specified value is different from null and undefined.</summary> - /// <param name="value" mayBeNull="true" optional="true">Value to check.</param> - /// <returns type="Boolean">true if the value is assigned; false otherwise.</returns> - return value !== null && value !== undefined; - }; - - var contains = function (arr, item) { - /// <summary>Checks whether the specified item is in the array.</summary> - /// <param name="arr" type="Array" optional="false" mayBeNull="false">Array to check in.</param> - /// <param name="item">Item to look for.</param> - /// <returns type="Boolean">true if the item is contained, false otherwise.</returns> - - var i, len; - for (i = 0, len = arr.length; i < len; i++) { - if (arr[i] === item) { - return true; - } - } - - return false; - }; - - var defined = function (a, b) { - /// <summary>Given two values, picks the first one that is not undefined.</summary> - /// <param name="a">First value.</param> - /// <param name="b">Second value.</param> - /// <returns>a if it's a defined value; else b.</returns> - return (a !== undefined) ? a : b; - }; - - var delay = function (callback) { - /// <summary>Delays the invocation of the specified function until execution unwinds.</summary> - /// <param name="callback" type="Function">Callback function.</param> - if (arguments.length === 1) { - window.setTimeout(callback, 0); - return; - } - - var args = Array.prototype.slice.call(arguments, 1); - window.setTimeout(function () { - callback.apply(this, args); - }, 0); - }; - - - var extend = function (target, values) { - /// <summary>Extends the target with the specified values.</summary> - /// <param name="target" type="Object">Object to add properties to.</param> - /// <param name="values" type="Object">Object with properties to add into target.</param> - /// <returns type="Object">The target object.</returns> - - for (var name in values) { - target[name] = values[name]; - } - - return target; - }; - - var find = function (arr, callback) { - /// <summary>Returns the first item in the array that makes the callback function true.</summary> - /// <param name="arr" type="Array" optional="false" mayBeNull="true">Array to check in.</param> - /// <param name="callback" type="Function">Callback function to invoke once per item in the array.</param> - /// <returns>The first item that makes the callback return true; null otherwise or if the array is null.</returns> - - if (arr) { - var i, len; - for (i = 0, len = arr.length; i < len; i++) { - if (callback(arr[i])) { - return arr[i]; - } - } - } - return null; - }; - - var isArray = function (value) { - /// <summary>Checks whether the specified value is an array object.</summary> - /// <param name="value">Value to check.</param> - /// <returns type="Boolean">true if the value is an array object; false otherwise.</returns> - - return Object.prototype.toString.call(value) === "[object Array]"; - }; - - var isDate = function (value) { - /// <summary>Checks whether the specified value is a Date object.</summary> - /// <param name="value">Value to check.</param> - /// <returns type="Boolean">true if the value is a Date object; false otherwise.</returns> - - return Object.prototype.toString.call(value) === "[object Date]"; - }; - - var isObject = function (value) { - /// <summary>Tests whether a value is an object.</summary> - /// <param name="value">Value to test.</param> - /// <remarks> - /// Per javascript rules, null and array values are objects and will cause this function to return true. - /// </remarks> - /// <returns type="Boolean">True is the value is an object; false otherwise.</returns> - - return typeof value === "object"; - }; - - var parseInt10 = function (value) { - /// <summary>Parses a value in base 10.</summary> - /// <param name="value" type="String">String value to parse.</param> - /// <returns type="Number">The parsed value, NaN if not a valid value.</returns> - - return parseInt(value, 10); - }; - - var renameProperty = function (obj, oldName, newName) { - /// <summary>Renames a property in an object.</summary> - /// <param name="obj" type="Object">Object in which the property will be renamed.</param> - /// <param name="oldName" type="String">Name of the property that will be renamed.</param> - /// <param name="newName" type="String">New name of the property.</param> - /// <remarks> - /// This function will not do anything if the object doesn't own a property with the specified old name. - /// </remarks> - - if (obj.hasOwnProperty(oldName)) { - obj[newName] = obj[oldName]; - delete obj[oldName]; - } - }; - - var throwErrorCallback = function (error) { - /// <summary>Default error handler.</summary> - /// <param name="error" type="Object">Error to handle.</param> - throw error; - }; - - var trimString = function (str) { - /// <summary>Removes leading and trailing whitespaces from a string.</summary> - /// <param name="str" type="String" optional="false" mayBeNull="false">String to trim</param> - /// <returns type="String">The string with no leading or trailing whitespace.</returns> - - if (str.trim) { - return str.trim(); - } - - return str.replace(/^\s+|\s+$/g, ''); - }; - - var undefinedDefault = function (value, defaultValue) { - /// <summary>Returns a default value in place of undefined.</summary> - /// <param name="value" mayBeNull="true" optional="true">Value to check.</param> - /// <param name="defaultValue">Value to return if value is undefined.</param> - /// <returns>value if it's defined; defaultValue otherwise.</returns> - /// <remarks> - /// This should only be used for cases where falsy values are valid; - /// otherwise the pattern should be 'x = (value) ? value : defaultValue;'. - /// </remarks> - return (value !== undefined) ? value : defaultValue; - }; - - // Regular expression that splits a uri into its components: - // 0 - is the matched string. - // 1 - is the scheme. - // 2 - is the authority. - // 3 - is the path. - // 4 - is the query. - // 5 - is the fragment. - var uriRegEx = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#:]+)?(\?[^#]*)?(#.*)?/; - var uriPartNames = ["scheme", "authority", "path", "query", "fragment"]; - - var getURIInfo = function (uri) { - /// <summary>Gets information about the components of the specified URI.</summary> - /// <param name="uri" type="String">URI to get information from.</param> - /// <returns type="Object"> - /// An object with an isAbsolute flag and part names (scheme, authority, etc.) if available. - /// </returns> - - var result = { isAbsolute: false }; - - if (uri) { - var matches = uriRegEx.exec(uri); - if (matches) { - var i, len; - for (i = 0, len = uriPartNames.length; i < len; i++) { - if (matches[i + 1]) { - result[uriPartNames[i]] = matches[i + 1]; - } - } - } - if (result.scheme) { - result.isAbsolute = true; - } - } - - return result; - }; - - var getURIFromInfo = function (uriInfo) { - /// <summary>Builds a URI string from its components.</summary> - /// <param name="uriInfo" type="Object"> An object with uri parts (scheme, authority, etc.).</param> - /// <returns type="String">URI string.</returns> - - return "".concat( - uriInfo.scheme || "", - uriInfo.authority || "", - uriInfo.path || "", - uriInfo.query || "", - uriInfo.fragment || ""); - }; - - // Regular expression that splits a uri authority into its subcomponents: - // 0 - is the matched string. - // 1 - is the userinfo subcomponent. - // 2 - is the host subcomponent. - // 3 - is the port component. - var uriAuthorityRegEx = /^\/{0,2}(?:([^@]*)@)?([^:]+)(?::{1}(\d+))?/; - - // Regular expression that matches percentage enconded octects (i.e %20 or %3A); - var pctEncodingRegEx = /%[0-9A-F]{2}/ig; - - var normalizeURICase = function (uri) { - /// <summary>Normalizes the casing of a URI.</summary> - /// <param name="uri" type="String">URI to normalize, absolute or relative.</param> - /// <returns type="String">The URI normalized to lower case.</returns> - - var uriInfo = getURIInfo(uri); - var scheme = uriInfo.scheme; - var authority = uriInfo.authority; - - if (scheme) { - uriInfo.scheme = scheme.toLowerCase(); - if (authority) { - var matches = uriAuthorityRegEx.exec(authority); - if (matches) { - uriInfo.authority = "//" + - (matches[1] ? matches[1] + "@" : "") + - (matches[2].toLowerCase()) + - (matches[3] ? ":" + matches[3] : ""); - } - } - } - - uri = getURIFromInfo(uriInfo); - - return uri.replace(pctEncodingRegEx, function (str) { - return str.toLowerCase(); - }); - }; - - var normalizeURI = function (uri, base) { - /// <summary>Normalizes a possibly relative URI with a base URI.</summary> - /// <param name="uri" type="String">URI to normalize, absolute or relative.</param> - /// <param name="base" type="String" mayBeNull="true">Base URI to compose with.</param> - /// <returns type="String">The composed URI if relative; the original one if absolute.</returns> - - if (!base) { - return uri; - } - - var uriInfo = getURIInfo(uri); - if (uriInfo.isAbsolute) { - return uri; - } - - var baseInfo = getURIInfo(base); - var normInfo = {}; - var path; - - if (uriInfo.authority) { - normInfo.authority = uriInfo.authority; - path = uriInfo.path; - normInfo.query = uriInfo.query; - } else { - if (!uriInfo.path) { - path = baseInfo.path; - normInfo.query = uriInfo.query || baseInfo.query; - } else { - if (uriInfo.path.charAt(0) === '/') { - path = uriInfo.path; - } else { - path = mergeUriPathWithBase(uriInfo.path, baseInfo.path); - } - normInfo.query = uriInfo.query; - } - normInfo.authority = baseInfo.authority; - } - - normInfo.path = removeDotsFromPath(path); - - normInfo.scheme = baseInfo.scheme; - normInfo.fragment = uriInfo.fragment; - - return getURIFromInfo(normInfo); - }; - - var mergeUriPathWithBase = function (uriPath, basePath) { - /// <summary>Merges the path of a relative URI and a base URI.</summary> - /// <param name="uriPath" type="String>Relative URI path.</param> - /// <param name="basePath" type="String">Base URI path.</param> - /// <returns type="String">A string with the merged path.</returns> - - var path = "/"; - var end; - - if (basePath) { - end = basePath.lastIndexOf("/"); - path = basePath.substring(0, end); - - if (path.charAt(path.length - 1) !== "/") { - path = path + "/"; - } - } - - return path + uriPath; - }; - - var removeDotsFromPath = function (path) { - /// <summary>Removes the special folders . and .. from a URI's path.</summary> - /// <param name="path" type="string">URI path component.</param> - /// <returns type="String">Path without any . and .. folders.</returns> - - var result = ""; - var segment = ""; - var end; - - while (path) { - if (path.indexOf("..") === 0 || path.indexOf(".") === 0) { - path = path.replace(/^\.\.?\/?/g, ""); - } else if (path.indexOf("/..") === 0) { - path = path.replace(/^\/\..\/?/g, "/"); - end = result.lastIndexOf("/"); - if (end === -1) { - result = ""; - } else { - result = result.substring(0, end); - } - } else if (path.indexOf("/.") === 0) { - path = path.replace(/^\/\.\/?/g, "/"); - } else { - segment = path; - end = path.indexOf("/", 1); - if (end !== -1) { - segment = path.substring(0, end); - } - result = result + segment; - path = path.replace(segment, ""); - } - } - return result; - }; - - var convertByteArrayToHexString = function (str) { - var arr = []; - if (window.atob === undefined) { - arr = decodeBase64(str); - } else { - var binaryStr = window.atob(str); - for (var i = 0; i < binaryStr.length; i++) { - arr.push(binaryStr.charCodeAt(i)); - } - } - var hexValue = ""; - var hexValues = "0123456789ABCDEF"; - for (var j = 0; j < arr.length; j++) { - var t = arr[j]; - hexValue += hexValues[t >> 4]; - hexValue += hexValues[t & 0x0F]; - } - return hexValue; - }; - - var decodeBase64 = function (str) { - var binaryString = ""; - for (var i = 0; i < str.length; i++) { - var base65IndexValue = getBase64IndexValue(str[i]); - var binaryValue = ""; - if (base65IndexValue !== null) { - binaryValue = base65IndexValue.toString(2); - binaryString += addBase64Padding(binaryValue); - } - } - var byteArray = []; - var numberOfBytes = parseInt(binaryString.length / 8, 10); - for (i = 0; i < numberOfBytes; i++) { - var intValue = parseInt(binaryString.substring(i * 8, (i + 1) * 8), 2); - byteArray.push(intValue); - } - return byteArray; - }; - - var getBase64IndexValue = function (character) { - var asciiCode = character.charCodeAt(0); - var asciiOfA = 65; - var differenceBetweenZanda = 6; - if (asciiCode >= 65 && asciiCode <= 90) { // between "A" and "Z" inclusive - return asciiCode - asciiOfA; - } else if (asciiCode >= 97 && asciiCode <= 122) { // between 'a' and 'z' inclusive - return asciiCode - asciiOfA - differenceBetweenZanda; - } else if (asciiCode >= 48 && asciiCode <= 57) { // between '0' and '9' inclusive - return asciiCode + 4; - } else if (character == "+") { - return 62; - } else if (character == "/") { - return 63; - } else { - return null; - } - }; - - var addBase64Padding = function (binaryString) { - while (binaryString.length < 6) { - binaryString = "0" + binaryString; - } - return binaryString; - }; - - - // URI prefixes to generate smaller code. - var http = "http://"; - var w3org = http + "www.w3.org/"; // http://www.w3.org/ - - var xhtmlNS = w3org + "1999/xhtml"; // http://www.w3.org/1999/xhtml - var xmlnsNS = w3org + "2000/xmlns/"; // http://www.w3.org/2000/xmlns/ - var xmlNS = w3org + "XML/1998/namespace"; // http://www.w3.org/XML/1998/namespace - - var mozillaParserErroNS = http + "www.mozilla.org/newlayout/xml/parsererror.xml"; - - var hasLeadingOrTrailingWhitespace = function (text) { - /// <summary>Checks whether the specified string has leading or trailing spaces.</summary> - /// <param name="text" type="String">String to check.</param> - /// <returns type="Boolean">true if text has any leading or trailing whitespace; false otherwise.</returns> - - var re = /(^\s)|(\s$)/; - return re.test(text); - }; - - var isWhitespace = function (text) { - /// <summary>Determines whether the specified text is empty or whitespace.</summary> - /// <param name="text" type="String">Value to inspect.</param> - /// <returns type="Boolean">true if the text value is empty or all whitespace; false otherwise.</returns> - - var ws = /^\s*$/; - return text === null || ws.test(text); - }; - - var isWhitespacePreserveContext = function (domElement) { - /// <summary>Determines whether the specified element has xml:space='preserve' applied.</summary> - /// <param name="domElement">Element to inspect.</param> - /// <returns type="Boolean">Whether xml:space='preserve' is in effect.</returns> - - while (domElement !== null && domElement.nodeType === 1) { - var val = xmlAttributeValue(domElement, "space", xmlNS); - if (val === "preserve") { - return true; - } else if (val === "default") { - break; - } else { - domElement = domElement.parentNode; - } - } - - return false; - }; - - var isXmlNSDeclaration = function (domAttribute) { - /// <summary>Determines whether the attribute is a XML namespace declaration.</summary> - /// <param name="domAttribute">Element to inspect.</param> - /// <returns type="Boolean"> - /// True if the attribute is a namespace declaration (its name is 'xmlns' or starts with 'xmlns:'; false otherwise. - /// </returns> - - var nodeName = domAttribute.nodeName; - return nodeName == "xmlns" || nodeName.indexOf("xmlns:") === 0; - }; - - var safeSetProperty = function (obj, name, value) { - /// <summary>Safely set as property in an object by invoking obj.setProperty.</summary> - /// <param name="obj">Object that exposes a setProperty method.</param> - /// <param name="name" type="String" mayBeNull="false">Property name.</param> - /// <param name="value">Property value.</param> - - try { - obj.setProperty(name, value); - } catch (_) { } - }; - - var msXmlDom3 = function () { - /// <summary>Creates an configures new MSXML 3.0 ActiveX object.</summary> - /// <remakrs> - /// This function throws any exception that occurs during the creation - /// of the MSXML 3.0 ActiveX object. - /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns> - - var msxml3 = activeXObject("Msxml2.DOMDocument.3.0"); - if (msxml3) { - safeSetProperty(msxml3, "ProhibitDTD", true); - safeSetProperty(msxml3, "MaxElementDepth", 256); - safeSetProperty(msxml3, "AllowDocumentFunction", false); - safeSetProperty(msxml3, "AllowXsltScript", false); - } - return msxml3; - }; - - var msXmlDom = function () { - /// <summary>Creates an configures new MSXML 6.0 or MSXML 3.0 ActiveX object.</summary> - /// <remakrs> - /// This function will try to create a new MSXML 6.0 ActiveX object. If it fails then - /// it will fallback to create a new MSXML 3.0 ActiveX object. Any exception that - /// happens during the creation of the MSXML 6.0 will be handled by the function while - /// the ones that happend during the creation of the MSXML 3.0 will be thrown. - /// <returns type="Object">New MSXML 3.0 ActiveX object.</returns> - - try { - var msxml = activeXObject("Msxml2.DOMDocument.6.0"); - if (msxml) { - msxml.async = true; - } - return msxml; - } catch (_) { - return msXmlDom3(); - } - }; - - var msXmlParse = function (text) { - /// <summary>Parses an XML string using the MSXML DOM.</summary> - /// <remakrs> - /// This function throws any exception that occurs during the creation - /// of the MSXML ActiveX object. It also will throw an exception - /// in case of a parsing error. - /// <returns type="Object">New MSXML DOMDocument node representing the parsed XML string.</returns> - - var dom = msXmlDom(); - if (!dom) { - return null; - } - - dom.loadXML(text); - var parseError = dom.parseError; - if (parseError.errorCode !== 0) { - xmlThrowParserError(parseError.reason, parseError.srcText, text); - } - return dom; - }; - - var xmlThrowParserError = function (exceptionOrReason, srcText, errorXmlText) { - /// <summary>Throws a new exception containing XML parsing error information.</summary> - /// <param name="exceptionOrReason"> - /// String indicatin the reason of the parsing failure or - /// Object detailing the parsing error. - /// </param> - /// <param name="srcText" type="String"> - /// String indicating the part of the XML string that caused the parsing error. - /// </param> - /// <param name="errorXmlText" type="String">XML string for wich the parsing failed.</param> - - if (typeof exceptionOrReason === "string") { - exceptionOrReason = { message: exceptionOrReason }; - } - throw extend(exceptionOrReason, { srcText: srcText || "", errorXmlText: errorXmlText || "" }); - }; - - var xmlParse = function (text) { - /// <summary>Returns an XML DOM document from the specified text.</summary> - /// <param name="text" type="String">Document text.</param> - /// <returns>XML DOM document.</returns> - /// <remarks>This function will throw an exception in case of a parse error.</remarks> - - var domParser = window.DOMParser && new window.DOMParser(); - var dom; - - if (!domParser) { - dom = msXmlParse(text); - if (!dom) { - xmlThrowParserError("XML DOM parser not supported"); - } - return dom; - } - - try { - dom = domParser.parseFromString(text, "text/xml"); - } catch (e) { - xmlThrowParserError(e, "", text); - } - - var element = dom.documentElement; - var nsURI = element.namespaceURI; - var localName = xmlLocalName(element); - - // Firefox reports errors by returing the DOM for an xml document describing the problem. - if (localName === "parsererror" && nsURI === mozillaParserErroNS) { - var srcTextElement = xmlFirstChildElement(element, mozillaParserErroNS, "sourcetext"); - var srcText = srcTextElement ? xmlNodeValue(srcTextElement) : ""; - xmlThrowParserError(xmlInnerText(element) || "", srcText, text); - } - - // Chrome (and maybe other webkit based browsers) report errors by injecting a header with an error message. - // The error may be localized, so instead we simply check for a header as the - // top element or descendant child of the document. - if (localName === "h3" && nsURI === xhtmlNS || xmlFirstDescendantElement(element, xhtmlNS, "h3")) { - var reason = ""; - var siblings = []; - var cursor = element.firstChild; - while (cursor) { - if (cursor.nodeType === 1) { - reason += xmlInnerText(cursor) || ""; - } - siblings.push(cursor.nextSibling); - cursor = cursor.firstChild || siblings.shift(); - } - reason += xmlInnerText(element) || ""; - xmlThrowParserError(reason, "", text); - } - - return dom; - }; - - var xmlQualifiedName = function (prefix, name) { - /// <summary>Builds a XML qualified name string in the form of "prefix:name".</summary> - /// <param name="prefix" type="String" maybeNull="true">Prefix string.</param> - /// <param name="name" type="String">Name string to qualify with the prefix.</param> - /// <returns type="String">Qualified name.</returns> - - return prefix ? prefix + ":" + name : name; - }; - - var xmlAppendText = function (domNode, textNode) { - /// <summary>Appends a text node into the specified DOM element node.</summary> - /// <param name="domNode">DOM node for the element.</param> - /// <param name="text" type="String" mayBeNull="false">Text to append as a child of element.</param> - if (hasLeadingOrTrailingWhitespace(textNode.data)) { - var attr = xmlAttributeNode(domNode, xmlNS, "space"); - if (!attr) { - attr = xmlNewAttribute(domNode.ownerDocument, xmlNS, xmlQualifiedName("xml", "space")); - xmlAppendChild(domNode, attr); - } - attr.value = "preserve"; - } - domNode.appendChild(textNode); - return domNode; - }; - - var xmlAttributes = function (element, onAttributeCallback) { - /// <summary>Iterates through the XML element's attributes and invokes the callback function for each one.</summary> - /// <param name="element">Wrapped element to iterate over.</param> - /// <param name="onAttributeCallback" type="Function">Callback function to invoke with wrapped attribute nodes.</param> - - var attributes = element.attributes; - var i, len; - for (i = 0, len = attributes.length; i < len; i++) { - onAttributeCallback(attributes.item(i)); - } - }; - - var xmlAttributeValue = function (domNode, localName, nsURI) { - /// <summary>Returns the value of a DOM element's attribute.</summary> - /// <param name="domNode">DOM node for the owning element.</param> - /// <param name="localName" type="String">Local name of the attribute.</param> - /// <param name="nsURI" type="String">Namespace URI of the attribute.</param> - /// <returns type="String" maybeNull="true">The attribute value, null if not found.</returns> - - var attribute = xmlAttributeNode(domNode, localName, nsURI); - return attribute ? xmlNodeValue(attribute) : null; - }; - - var xmlAttributeNode = function (domNode, localName, nsURI) { - /// <summary>Gets an attribute node from a DOM element.</summary> - /// <param name="domNode">DOM node for the owning element.</param> - /// <param name="localName" type="String">Local name of the attribute.</param> - /// <param name="nsURI" type="String">Namespace URI of the attribute.</param> - /// <returns>The attribute node, null if not found.</returns> - - var attributes = domNode.attributes; - if (attributes.getNamedItemNS) { - return attributes.getNamedItemNS(nsURI || null, localName); - } - - return attributes.getQualifiedItem(localName, nsURI) || null; - }; - - var xmlBaseURI = function (domNode, baseURI) { - /// <summary>Gets the value of the xml:base attribute on the specified element.</summary> - /// <param name="domNode">Element to get xml:base attribute value from.</param> - /// <param name="baseURI" mayBeNull="true" optional="true">Base URI used to normalize the value of the xml:base attribute.</param> - /// <returns type="String">Value of the xml:base attribute if found; the baseURI or null otherwise.</returns> - - var base = xmlAttributeNode(domNode, "base", xmlNS); - return (base ? normalizeURI(base.value, baseURI) : baseURI) || null; - }; - - - var xmlChildElements = function (domNode, onElementCallback) { - /// <summary>Iterates through the XML element's child DOM elements and invokes the callback function for each one.</summary> - /// <param name="element">DOM Node containing the DOM elements to iterate over.</param> - /// <param name="onElementCallback" type="Function">Callback function to invoke for each child DOM element.</param> - - xmlTraverse(domNode, /*recursive*/false, function (child) { - if (child.nodeType === 1) { - onElementCallback(child); - } - // continue traversing. - return true; - }); - }; - - var xmlFindElementByPath = function (root, namespaceURI, path) { - /// <summary>Gets the descendant element under root that corresponds to the specified path and namespace URI.</summary> - /// <param name="root">DOM element node from which to get the descendant element.</param> - /// <param name="namespaceURI" type="String">The namespace URI of the element to match.</param> - /// <param name="path" type="String">Path to the desired descendant element.</param> - /// <returns>The element specified by path and namespace URI.</returns> - /// <remarks> - /// All the elements in the path are matched against namespaceURI. - /// The function will stop searching on the first element that doesn't match the namespace and the path. - /// </remarks> - - var parts = path.split("/"); - var i, len; - for (i = 0, len = parts.length; i < len; i++) { - root = root && xmlFirstChildElement(root, namespaceURI, parts[i]); - } - return root || null; - }; - - var xmlFindNodeByPath = function (root, namespaceURI, path) { - /// <summary>Gets the DOM element or DOM attribute node under root that corresponds to the specified path and namespace URI.</summary> - /// <param name="root">DOM element node from which to get the descendant node.</param> - /// <param name="namespaceURI" type="String">The namespace URI of the node to match.</param> - /// <param name="path" type="String">Path to the desired descendant node.</param> - /// <returns>The node specified by path and namespace URI.</returns> - /// <remarks> - /// This function will traverse the path and match each node associated to a path segement against the namespace URI. - /// The traversal stops when the whole path has been exahusted or a node that doesn't belogong the specified namespace is encountered. - /// - /// The last segment of the path may be decorated with a starting @ character to indicate that the desired node is a DOM attribute. - /// </remarks> - - var lastSegmentStart = path.lastIndexOf("/"); - var nodePath = path.substring(lastSegmentStart + 1); - var parentPath = path.substring(0, lastSegmentStart); - - var node = parentPath ? xmlFindElementByPath(root, namespaceURI, parentPath) : root; - if (node) { - if (nodePath.charAt(0) === "@") { - return xmlAttributeNode(node, nodePath.substring(1), namespaceURI); - } - return xmlFirstChildElement(node, namespaceURI, nodePath); - } - return null; - }; - - var xmlFirstChildElement = function (domNode, namespaceURI, localName) { - /// <summary>Returns the first child DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary> - /// <param name="domNode">DOM node from which the child DOM element is going to be retrieved.</param> - /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param> - /// <param name="localName" type="String" optional="true">Name of the element to match.</param> - /// <returns>The node's first child DOM element that matches the specified namespace URI and local name; null otherwise.</returns> - - return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/false); - }; - - var xmlFirstDescendantElement = function (domNode, namespaceURI, localName) { - /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary> - /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param> - /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param> - /// <param name="localName" type="String" optional="true">Name of the element to match.</param> - /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns> - - if (domNode.getElementsByTagNameNS) { - var result = domNode.getElementsByTagNameNS(namespaceURI, localName); - return result.length > 0 ? result[0] : null; - } - return xmlFirstElementMaybeRecursive(domNode, namespaceURI, localName, /*recursive*/true); - }; - - var xmlFirstElementMaybeRecursive = function (domNode, namespaceURI, localName, recursive) { - /// <summary>Returns the first descendant DOM element under the specified DOM node that matches the specified namespace URI and local name.</summary> - /// <param name="domNode">DOM node from which the descendant DOM element is going to be retrieved.</param> - /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param> - /// <param name="localName" type="String" optional="true">Name of the element to match.</param> - /// <param name="recursive" type="Boolean"> - /// True if the search should include all the descendants of the DOM node. - /// False if the search should be scoped only to the direct children of the DOM node. - /// </param> - /// <returns>The node's first descendant DOM element that matches the specified namespace URI and local name; null otherwise.</returns> - - var firstElement = null; - xmlTraverse(domNode, recursive, function (child) { - if (child.nodeType === 1) { - var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(child) === namespaceURI; - var isExpectedNodeName = !localName || xmlLocalName(child) === localName; - - if (isExpectedNamespace && isExpectedNodeName) { - firstElement = child; - } - } - return firstElement === null; - }); - return firstElement; - }; - - var xmlInnerText = function (xmlElement) { - /// <summary>Gets the concatenated value of all immediate child text and CDATA nodes for the specified element.</summary> - /// <param name="domElement">Element to get values for.</param> - /// <returns type="String">Text for all direct children.</returns> - - var result = null; - var root = (xmlElement.nodeType === 9 && xmlElement.documentElement) ? xmlElement.documentElement : xmlElement; - var whitespaceAlreadyRemoved = root.ownerDocument.preserveWhiteSpace === false; - var whitespacePreserveContext; - - xmlTraverse(root, false, function (child) { - if (child.nodeType === 3 || child.nodeType === 4) { - // isElementContentWhitespace indicates that this is 'ignorable whitespace', - // but it's not defined by all browsers, and does not honor xml:space='preserve' - // in some implementations. - // - // If we can't tell either way, we walk up the tree to figure out whether - // xml:space is set to preserve; otherwise we discard pure-whitespace. - // - // For example <a> <b>1</b></a>. The space between <a> and <b> is usually 'ignorable'. - var text = xmlNodeValue(child); - var shouldInclude = whitespaceAlreadyRemoved || !isWhitespace(text); - if (!shouldInclude) { - // Walk up the tree to figure out whether we are in xml:space='preserve' context - // for the cursor (needs to happen only once). - if (whitespacePreserveContext === undefined) { - whitespacePreserveContext = isWhitespacePreserveContext(root); - } - - shouldInclude = whitespacePreserveContext; - } - - if (shouldInclude) { - if (!result) { - result = text; - } else { - result += text; - } - } - } - // Continue traversing? - return true; - }); - return result; - }; - - var xmlLocalName = function (domNode) { - /// <summary>Returns the localName of a XML node.</summary> - /// <param name="domNode">DOM node to get the value from.</param> - /// <returns type="String">localName of domNode.</returns> - - return domNode.localName || domNode.baseName; - }; - - var xmlNamespaceURI = function (domNode) { - /// <summary>Returns the namespace URI of a XML node.</summary> - /// <param name="node">DOM node to get the value from.</param> - /// <returns type="String">Namespace URI of domNode.</returns> - - return domNode.namespaceURI || null; - }; - - var xmlNodeValue = function (domNode) { - /// <summary>Returns the value or the inner text of a XML node.</summary> - /// <param name="node">DOM node to get the value from.</param> - /// <returns>Value of the domNode or the inner text if domNode represents a DOM element node.</returns> - - if (domNode.nodeType === 1) { - return xmlInnerText(domNode); - } - return domNode.nodeValue; - }; - - var xmlTraverse = function (domNode, recursive, onChildCallback) { - /// <summary>Walks through the descendants of the domNode and invokes a callback for each node.</summary> - /// <param name="domNode">DOM node whose descendants are going to be traversed.</param> - /// <param name="recursive" type="Boolean"> - /// True if the traversal should include all the descenants of the DOM node. - /// False if the traversal should be scoped only to the direct children of the DOM node. - /// </param> - /// <returns type="String">Namespace URI of node.</returns> - - var subtrees = []; - var child = domNode.firstChild; - var proceed = true; - while (child && proceed) { - proceed = onChildCallback(child); - if (proceed) { - if (recursive && child.firstChild) { - subtrees.push(child.firstChild); - } - child = child.nextSibling || subtrees.shift(); - } - } - }; - - var xmlSiblingElement = function (domNode, namespaceURI, localName) { - /// <summary>Returns the next sibling DOM element of the specified DOM node.</summary> - /// <param name="domNode">DOM node from which the next sibling is going to be retrieved.</param> - /// <param name="namespaceURI" type="String" optional="true">The namespace URI of the element to match.</param> - /// <param name="localName" type="String" optional="true">Name of the element to match.</param> - /// <returns>The node's next sibling DOM element, null if there is none.</returns> - - var sibling = domNode.nextSibling; - while (sibling) { - if (sibling.nodeType === 1) { - var isExpectedNamespace = !namespaceURI || xmlNamespaceURI(sibling) === namespaceURI; - var isExpectedNodeName = !localName || xmlLocalName(sibling) === localName; - - if (isExpectedNamespace && isExpectedNodeName) { - return sibling; - } - } - sibling = sibling.nextSibling; - } - return null; - }; - - var xmlDom = function () { - /// <summary>Creates a new empty DOM document node.</summary> - /// <returns>New DOM document node.</returns> - /// <remarks> - /// This function will first try to create a native DOM document using - /// the browsers createDocument function. If the browser doesn't - /// support this but supports ActiveXObject, then an attempt to create - /// an MSXML 6.0 DOM will be made. If this attempt fails too, then an attempt - /// for creating an MXSML 3.0 DOM will be made. If this last attemp fails or - /// the browser doesn't support ActiveXObject then an exception will be thrown. - /// </remarks> - - var implementation = window.document.implementation; - return (implementation && implementation.createDocument) ? - implementation.createDocument(null, null, null) : - msXmlDom(); - }; - - var xmlAppendChildren = function (parent, children) { - /// <summary>Appends a collection of child nodes or string values to a parent DOM node.</summary> - /// <param name="parent">DOM node to which the children will be appended.</param> - /// <param name="children" type="Array">Array containing DOM nodes or string values that will be appended to the parent.</param> - /// <returns>The parent with the appended children or string values.</returns> - /// <remarks> - /// If a value in the children collection is a string, then a new DOM text node is going to be created - /// for it and then appended to the parent. - /// </remarks> - - if (!isArray(children)) { - return xmlAppendChild(parent, children); - } - - var i, len; - for (i = 0, len = children.length; i < len; i++) { - children[i] && xmlAppendChild(parent, children[i]); - } - return parent; - }; - - var xmlAppendChild = function (parent, child) { - /// <summary>Appends a child node or a string value to a parent DOM node.</summary> - /// <param name="parent">DOM node to which the child will be appended.</param> - /// <param name="child">Child DOM node or string value to append to the parent.</param> - /// <returns>The parent with the appended child or string value.</returns> - /// <remarks> - /// If child is a string value, then a new DOM text node is going to be created - /// for it and then appended to the parent. - /// </remarks> - - if (child) { - if (typeof child === "string") { - return xmlAppendText(parent, xmlNewText(parent.ownerDocument, child)); - } - if (child.nodeType === 2) { - parent.setAttributeNodeNS ? parent.setAttributeNodeNS(child) : parent.setAttributeNode(child); - } else { - parent.appendChild(child); - } - } - return parent; - }; - - var xmlNewAttribute = function (dom, namespaceURI, qualifiedName, value) { - /// <summary>Creates a new DOM attribute node.</summary> - /// <param name="dom">DOM document used to create the attribute.</param> - /// <param name="prefix" type="String">Namespace prefix.</param> - /// <param name="namespaceURI" type="String">Namespace URI.</param> - /// <returns>DOM attribute node for the namespace declaration.</returns> - - var attribute = - dom.createAttributeNS && dom.createAttributeNS(namespaceURI, qualifiedName) || - dom.createNode(2, qualifiedName, namespaceURI || undefined); - - attribute.value = value || ""; - return attribute; - }; - - var xmlNewElement = function (dom, nampespaceURI, qualifiedName, children) { - /// <summary>Creates a new DOM element node.</summary> - /// <param name="dom">DOM document used to create the DOM element.</param> - /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element.</param> - /// <param name="qualifiedName" type="String">Qualified name in the form of "prefix:name" of the new DOM element.</param> - /// <param name="children" type="Array" optional="true"> - /// Collection of child DOM nodes or string values that are going to be appended to the new DOM element. - /// </param> - /// <returns>New DOM element.</returns> - /// <remarks> - /// If a value in the children collection is a string, then a new DOM text node is going to be created - /// for it and then appended to the new DOM element. - /// </remarks> - - var element = - dom.createElementNS && dom.createElementNS(nampespaceURI, qualifiedName) || - dom.createNode(1, qualifiedName, nampespaceURI || undefined); - - return xmlAppendChildren(element, children || []); - }; - - var xmlNewNSDeclaration = function (dom, namespaceURI, prefix) { - /// <summary>Creates a namespace declaration attribute.</summary> - /// <param name="dom">DOM document used to create the attribute.</param> - /// <param name="namespaceURI" type="String">Namespace URI.</param> - /// <param name="prefix" type="String">Namespace prefix.</param> - /// <returns>DOM attribute node for the namespace declaration.</returns> - - return xmlNewAttribute(dom, xmlnsNS, xmlQualifiedName("xmlns", prefix), namespaceURI); - }; - - var xmlNewFragment = function (dom, text) { - /// <summary>Creates a new DOM document fragment node for the specified xml text.</summary> - /// <param name="dom">DOM document from which the fragment node is going to be created.</param> - /// <param name="text" type="String" mayBeNull="false">XML text to be represented by the XmlFragment.</param> - /// <returns>New DOM document fragment object.</returns> - - var value = "<c>" + text + "</c>"; - var tempDom = xmlParse(value); - var tempRoot = tempDom.documentElement; - var imported = ("importNode" in dom) ? dom.importNode(tempRoot, true) : tempRoot; - var fragment = dom.createDocumentFragment(); - - var importedChild = imported.firstChild; - while (importedChild) { - fragment.appendChild(importedChild); - importedChild = importedChild.nextSibling; - } - return fragment; - }; - - var xmlNewText = function (dom, text) { - /// <summary>Creates new DOM text node.</summary> - /// <param name="dom">DOM document used to create the text node.</param> - /// <param name="text" type="String">Text value for the DOM text node.</param> - /// <returns>DOM text node.</returns> - - return dom.createTextNode(text); - }; - - var xmlNewNodeByPath = function (dom, root, namespaceURI, prefix, path) { - /// <summary>Creates a new DOM element or DOM attribute node as specified by path and appends it to the DOM tree pointed by root.</summary> - /// <param name="dom">DOM document used to create the new node.</param> - /// <param name="root">DOM element node used as root of the subtree on which the new nodes are going to be created.</param> - /// <param name="namespaceURI" type="String">Namespace URI of the new DOM element or attribute.</param> - /// <param name="namespacePrefix" type="String">Prefix used to qualify the name of the new DOM element or attribute.</param> - /// <param name="Path" type="String">Path string describing the location of the new DOM element or attribute from the root element.</param> - /// <returns>DOM element or attribute node for the last segment of the path.</returns> - /// <remarks> - /// This function will traverse the path and will create a new DOM element with the specified namespace URI and prefix - /// for each segment that doesn't have a matching element under root. - /// - /// The last segment of the path may be decorated with a starting @ character. In this case a new DOM attribute node - /// will be created. - /// </remarks> - - var name = ""; - var parts = path.split("/"); - var xmlFindNode = xmlFirstChildElement; - var xmlNewNode = xmlNewElement; - var xmlNode = root; - - var i, len; - for (i = 0, len = parts.length; i < len; i++) { - name = parts[i]; - if (name.charAt(0) === "@") { - name = name.substring(1); - xmlFindNode = xmlAttributeNode; - xmlNewNode = xmlNewAttribute; - } - - var childNode = xmlFindNode(xmlNode, namespaceURI, name); - if (!childNode) { - childNode = xmlNewNode(dom, namespaceURI, xmlQualifiedName(prefix, name)); - xmlAppendChild(xmlNode, childNode); - } - xmlNode = childNode; - } - return xmlNode; - }; - - var xmlSerialize = function (domNode) { - /// <summary> - /// Returns the text representation of the document to which the specified node belongs. - /// </summary> - /// <param name="root">Wrapped element in the document to serialize.</param> - /// <returns type="String">Serialized document.</returns> - - var xmlSerializer = window.XMLSerializer; - if (xmlSerializer) { - var serializer = new xmlSerializer(); - return serializer.serializeToString(domNode); - } - - if (domNode.xml) { - return domNode.xml; - } - - throw { message: "XML serialization unsupported" }; - }; - - var xmlSerializeDescendants = function (domNode) { - /// <summary>Returns the XML representation of the all the descendants of the node.</summary> - /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param> - /// <returns type="String">The XML representation of all the descendants of the node.</returns> - - var children = domNode.childNodes; - var i, len = children.length; - if (len === 0) { - return ""; - } - - // Some implementations of the XMLSerializer don't deal very well with fragments that - // don't have a DOMElement as their first child. The work around is to wrap all the - // nodes in a dummy root node named "c", serialize it and then just extract the text between - // the <c> and the </c> substrings. - - var dom = domNode.ownerDocument; - var fragment = dom.createDocumentFragment(); - var fragmentRoot = dom.createElement("c"); - - fragment.appendChild(fragmentRoot); - // Move the children to the fragment tree. - for (i = 0; i < len; i++) { - fragmentRoot.appendChild(children[i]); - } - - var xml = xmlSerialize(fragment); - xml = xml.substr(3, xml.length - 7); - - // Move the children back to the original dom tree. - for (i = 0; i < len; i++) { - domNode.appendChild(fragmentRoot.childNodes[i]); - } - - return xml; - }; - - var xmlSerializeNode = function (domNode) { - /// <summary>Returns the XML representation of the node and all its descendants.</summary> - /// <param name="domNode" optional="false" mayBeNull="false">Node to serialize.</param> - /// <returns type="String">The XML representation of the node and all its descendants.</returns> - - var xml = domNode.xml; - if (xml !== undefined) { - return xml; - } - - if (window.XMLSerializer) { - var serializer = new window.XMLSerializer(); - return serializer.serializeToString(domNode); - } - - throw { message: "XML serialization unsupported" }; - }; - - - - - var forwardCall = function (thisValue, name, returnValue) { - /// <summary>Creates a new function to forward a call.</summary> - /// <param name="thisValue" type="Object">Value to use as the 'this' object.</param> - /// <param name="name" type="String">Name of function to forward to.</param> - /// <param name="returnValue" type="Object">Return value for the forward call (helps keep identity when chaining calls).</param> - /// <returns type="Function">A new function that will forward a call.</returns> - - return function () { - thisValue[name].apply(thisValue, arguments); - return returnValue; - }; - }; - - var DjsDeferred = function () { - /// <summary>Initializes a new DjsDeferred object.</summary> - /// <remarks> - /// Compability Note A - Ordering of callbacks through chained 'then' invocations - /// - /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A - /// implies that .then() returns a distinct object. - //// - /// For compatibility with http://api.jquery.com/category/deferred-object/ - /// we return this same object. This affects ordering, as - /// the jQuery version will fire callbacks in registration - /// order regardless of whether they occur on the result - /// or the original object. - /// - /// Compability Note B - Fulfillment value - /// - /// The Wiki entry at http://wiki.commonjs.org/wiki/Promises/A - /// implies that the result of a success callback is the - /// fulfillment value of the object and is received by - /// other success callbacks that are chained. - /// - /// For compatibility with http://api.jquery.com/category/deferred-object/ - /// we disregard this value instead. - /// </remarks> - - this._arguments = undefined; - this._done = undefined; - this._fail = undefined; - this._resolved = false; - this._rejected = false; - }; - - DjsDeferred.prototype = { - then: function (fulfilledHandler, errorHandler /*, progressHandler */) { - /// <summary>Adds success and error callbacks for this deferred object.</summary> - /// <param name="fulfilledHandler" type="Function" mayBeNull="true" optional="true">Success callback.</param> - /// <param name="errorHandler" type="Function" mayBeNull="true" optional="true">Error callback.</param> - /// <remarks>See Compatibility Note A.</remarks> - - if (fulfilledHandler) { - if (!this._done) { - this._done = [fulfilledHandler]; - } else { - this._done.push(fulfilledHandler); - } - } - - if (errorHandler) { - if (!this._fail) { - this._fail = [errorHandler]; - } else { - this._fail.push(errorHandler); - } - } - - //// See Compatibility Note A in the DjsDeferred constructor. - //// if (!this._next) { - //// this._next = createDeferred(); - //// } - //// return this._next.promise(); - - if (this._resolved) { - this.resolve.apply(this, this._arguments); - } else if (this._rejected) { - this.reject.apply(this, this._arguments); - } - - return this; - }, - - resolve: function (/* args */) { - /// <summary>Invokes success callbacks for this deferred object.</summary> - /// <remarks>All arguments are forwarded to success callbacks.</remarks> - - - if (this._done) { - var i, len; - for (i = 0, len = this._done.length; i < len; i++) { - //// See Compability Note B - Fulfillment value. - //// var nextValue = - this._done[i].apply(null, arguments); - } - - //// See Compatibility Note A in the DjsDeferred constructor. - //// this._next.resolve(nextValue); - //// delete this._next; - - this._done = undefined; - this._resolved = false; - this._arguments = undefined; - } else { - this._resolved = true; - this._arguments = arguments; - } - }, - - reject: function (/* args */) { - /// <summary>Invokes error callbacks for this deferred object.</summary> - /// <remarks>All arguments are forwarded to error callbacks.</remarks> - if (this._fail) { - var i, len; - for (i = 0, len = this._fail.length; i < len; i++) { - this._fail[i].apply(null, arguments); - } - - this._fail = undefined; - this._rejected = false; - this._arguments = undefined; - } else { - this._rejected = true; - this._arguments = arguments; - } - }, - - promise: function () { - /// <summary>Returns a version of this object that has only the read-only methods available.</summary> - /// <returns>An object with only the promise object.</returns> - - var result = {}; - result.then = forwardCall(this, "then", result); - return result; - } - }; - - var createDeferred = function () { - /// <summary>Creates a deferred object.</summary> - /// <returns type="DjsDeferred"> - /// A new deferred object. If jQuery is installed, then a jQuery - /// Deferred object is returned, which provides a superset of features. - /// </returns> - - if (window.jQuery && window.jQuery.Deferred) { - return new window.jQuery.Deferred(); - } else { - return new DjsDeferred(); - } - }; - - - - - var dataItemTypeName = function (value, metadata) { - /// <summary>Gets the type name of a data item value that belongs to a feed, an entry, a complex type property, or a collection property.</summary> - /// <param name="value">Value of the data item from which the type name is going to be retrieved.</param> - /// <param name="metadata" type="object" optional="true">Object containing metadata about the data tiem.</param> - /// <remarks> - /// This function will first try to get the type name from the data item's value itself if it is an object with a __metadata property; otherwise - /// it will try to recover it from the metadata. If both attempts fail, it will return null. - /// </remarks> - /// <returns type="String">Data item type name; null if the type name cannot be found within the value or the metadata</returns> - - var valueTypeName = ((value && value.__metadata) || {}).type; - return valueTypeName || (metadata ? metadata.type : null); - }; - - var EDM = "Edm."; - var EDM_BINARY = EDM + "Binary"; - var EDM_BOOLEAN = EDM + "Boolean"; - var EDM_BYTE = EDM + "Byte"; - var EDM_DATETIME = EDM + "DateTime"; - var EDM_DATETIMEOFFSET = EDM + "DateTimeOffset"; - var EDM_DECIMAL = EDM + "Decimal"; - var EDM_DOUBLE = EDM + "Double"; - var EDM_GUID = EDM + "Guid"; - var EDM_INT16 = EDM + "Int16"; - var EDM_INT32 = EDM + "Int32"; - var EDM_INT64 = EDM + "Int64"; - var EDM_SBYTE = EDM + "SByte"; - var EDM_SINGLE = EDM + "Single"; - var EDM_STRING = EDM + "String"; - var EDM_TIME = EDM + "Time"; - - var EDM_GEOGRAPHY = EDM + "Geography"; - var EDM_GEOGRAPHY_POINT = EDM_GEOGRAPHY + "Point"; - var EDM_GEOGRAPHY_LINESTRING = EDM_GEOGRAPHY + "LineString"; - var EDM_GEOGRAPHY_POLYGON = EDM_GEOGRAPHY + "Polygon"; - var EDM_GEOGRAPHY_COLLECTION = EDM_GEOGRAPHY + "Collection"; - var EDM_GEOGRAPHY_MULTIPOLYGON = EDM_GEOGRAPHY + "MultiPolygon"; - var EDM_GEOGRAPHY_MULTILINESTRING = EDM_GEOGRAPHY + "MultiLineString"; - var EDM_GEOGRAPHY_MULTIPOINT = EDM_GEOGRAPHY + "MultiPoint"; - - var EDM_GEOMETRY = EDM + "Geometry"; - var EDM_GEOMETRY_POINT = EDM_GEOMETRY + "Point"; - var EDM_GEOMETRY_LINESTRING = EDM_GEOMETRY + "LineString"; - var EDM_GEOMETRY_POLYGON = EDM_GEOMETRY + "Polygon"; - var EDM_GEOMETRY_COLLECTION = EDM_GEOMETRY + "Collection"; - var EDM_GEOMETRY_MULTIPOLYGON = EDM_GEOMETRY + "MultiPolygon"; - var EDM_GEOMETRY_MULTILINESTRING = EDM_GEOMETRY + "MultiLineString"; - var EDM_GEOMETRY_MULTIPOINT = EDM_GEOMETRY + "MultiPoint"; - - var GEOJSON_POINT = "Point"; - var GEOJSON_LINESTRING = "LineString"; - var GEOJSON_POLYGON = "Polygon"; - var GEOJSON_MULTIPOINT = "MultiPoint"; - var GEOJSON_MULTILINESTRING = "MultiLineString"; - var GEOJSON_MULTIPOLYGON = "MultiPolygon"; - var GEOJSON_GEOMETRYCOLLECTION = "GeometryCollection"; - - var primitiveEdmTypes = [ - EDM_STRING, - EDM_INT32, - EDM_INT64, - EDM_BOOLEAN, - EDM_DOUBLE, - EDM_SINGLE, - EDM_DATETIME, - EDM_DATETIMEOFFSET, - EDM_TIME, - EDM_DECIMAL, - EDM_GUID, - EDM_BYTE, - EDM_INT16, - EDM_SBYTE, - EDM_BINARY - ]; - - var geometryEdmTypes = [ - EDM_GEOMETRY, - EDM_GEOMETRY_POINT, - EDM_GEOMETRY_LINESTRING, - EDM_GEOMETRY_POLYGON, - EDM_GEOMETRY_COLLECTION, - EDM_GEOMETRY_MULTIPOLYGON, - EDM_GEOMETRY_MULTILINESTRING, - EDM_GEOMETRY_MULTIPOINT - ]; - - var geographyEdmTypes = [ - EDM_GEOGRAPHY, - EDM_GEOGRAPHY_POINT, - EDM_GEOGRAPHY_LINESTRING, - EDM_GEOGRAPHY_POLYGON, - EDM_GEOGRAPHY_COLLECTION, - EDM_GEOGRAPHY_MULTIPOLYGON, - EDM_GEOGRAPHY_MULTILINESTRING, - EDM_GEOGRAPHY_MULTIPOINT - ]; - - var forEachSchema = function (metadata, callback) { - /// <summary>Invokes a function once per schema in metadata.</summary> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <param name="callback" type="Function">Callback function to invoke once per schema.</param> - /// <returns> - /// The first truthy value to be returned from the callback; null or the last falsy value otherwise. - /// </returns> - - if (!metadata) { - return null; - } - - if (isArray(metadata)) { - var i, len, result; - for (i = 0, len = metadata.length; i < len; i++) { - result = forEachSchema(metadata[i], callback); - if (result) { - return result; - } - } - - return null; - } else { - if (metadata.dataServices) { - return forEachSchema(metadata.dataServices.schema, callback); - } - - return callback(metadata); - } - }; - - var formatMilliseconds = function (ms, ns) { - /// <summary>Formats a millisecond and a nanosecond value into a single string.</summary> - /// <param name="ms" type="Number" mayBeNull="false">Number of milliseconds to format.</param> - /// <param name="ns" type="Number" mayBeNull="false">Number of nanoseconds to format.</param> - /// <returns type="String">Formatted text.</returns> - /// <remarks>If the value is already as string it's returned as-is.</remarks> - - // Avoid generating milliseconds if not necessary. - if (ms === 0) { - ms = ""; - } else { - ms = "." + formatNumberWidth(ms.toString(), 3); - } - if (ns > 0) { - if (ms === "") { - ms = ".000"; - } - ms += formatNumberWidth(ns.toString(), 4); - } - return ms; - }; - - var formatDateTimeOffset = function (value) { - /// <summary>Formats a DateTime or DateTimeOffset value a string.</summary> - /// <param name="value" type="Date" mayBeNull="false">Value to format.</param> - /// <returns type="String">Formatted text.</returns> - /// <remarks>If the value is already as string it's returned as-is.</remarks> - - if (typeof value === "string") { - return value; - } - - var hasOffset = isDateTimeOffset(value); - var offset = getCanonicalTimezone(value.__offset); - if (hasOffset && offset !== "Z") { - // We're about to change the value, so make a copy. - value = new Date(value.valueOf()); - - var timezone = parseTimezone(offset); - var hours = value.getUTCHours() + (timezone.d * timezone.h); - var minutes = value.getUTCMinutes() + (timezone.d * timezone.m); - - value.setUTCHours(hours, minutes); - } else if (!hasOffset) { - // Don't suffix a 'Z' for Edm.DateTime values. - offset = ""; - } - - var year = value.getUTCFullYear(); - var month = value.getUTCMonth() + 1; - var sign = ""; - if (year <= 0) { - year = -(year - 1); - sign = "-"; - } - - var ms = formatMilliseconds(value.getUTCMilliseconds(), value.__ns); - - return sign + - formatNumberWidth(year, 4) + "-" + - formatNumberWidth(month, 2) + "-" + - formatNumberWidth(value.getUTCDate(), 2) + "T" + - formatNumberWidth(value.getUTCHours(), 2) + ":" + - formatNumberWidth(value.getUTCMinutes(), 2) + ":" + - formatNumberWidth(value.getUTCSeconds(), 2) + - ms + offset; - }; - - var formatDuration = function (value) { - /// <summary>Converts a duration to a string in xsd:duration format.</summary> - /// <param name="value" type="Object">Object with ms and __edmType properties.</param> - /// <returns type="String">String representation of the time object in xsd:duration format.</returns> - - var ms = value.ms; - - var sign = ""; - if (ms < 0) { - sign = "-"; - ms = -ms; - } - - var days = Math.floor(ms / 86400000); - ms -= 86400000 * days; - var hours = Math.floor(ms / 3600000); - ms -= 3600000 * hours; - var minutes = Math.floor(ms / 60000); - ms -= 60000 * minutes; - var seconds = Math.floor(ms / 1000); - ms -= seconds * 1000; - - return sign + "P" + - formatNumberWidth(days, 2) + "DT" + - formatNumberWidth(hours, 2) + "H" + - formatNumberWidth(minutes, 2) + "M" + - formatNumberWidth(seconds, 2) + - formatMilliseconds(ms, value.ns) + "S"; - }; - - var formatNumberWidth = function (value, width, append) { - /// <summary>Formats the specified value to the given width.</summary> - /// <param name="value" type="Number">Number to format (non-negative).</param> - /// <param name="width" type="Number">Minimum width for number.</param> - /// <param name="append" type="Boolean">Flag indicating if the value is padded at the beginning (false) or at the end (true).</param> - /// <returns type="String">Text representation.</returns> - var result = value.toString(10); - while (result.length < width) { - if (append) { - result += "0"; - } else { - result = "0" + result; - } - } - - return result; - }; - - var getCanonicalTimezone = function (timezone) { - /// <summary>Gets the canonical timezone representation.</summary> - /// <param name="timezone" type="String">Timezone representation.</param> - /// <returns type="String">An 'Z' string if the timezone is absent or 0; the timezone otherwise.</returns> - - return (!timezone || timezone === "Z" || timezone === "+00:00" || timezone === "-00:00") ? "Z" : timezone; - }; - - var getCollectionType = function (typeName) { - /// <summary>Gets the type of a collection type name.</summary> - /// <param name="typeName" type="String">Type name of the collection.</param> - /// <returns type="String">Type of the collection; null if the type name is not a collection type.</returns> - - if (typeof typeName === "string") { - var end = typeName.indexOf(")", 10); - if (typeName.indexOf("Collection(") === 0 && end > 0) { - return typeName.substring(11, end); - } - } - return null; - }; - - var invokeRequest = function (request, success, error, handler, httpClient, context) { - /// <summary>Sends a request containing OData payload to a server.</summary> - /// <param name="request">Object that represents the request to be sent..</param> - /// <param name="success">Callback for a successful read operation.</param> - /// <param name="error">Callback for handling errors.</param> - /// <param name="handler">Handler for data serialization.</param> - /// <param name="httpClient">HTTP client layer.</param> - /// <param name="context">Context used for processing the request</param> - - return httpClient.request(request, function (response) { - try { - if (response.headers) { - normalizeHeaders(response.headers); - } - - if (response.data === undefined && response.statusCode !== 204) { - handler.read(response, context); - } - } catch (err) { - if (err.request === undefined) { - err.request = request; - } - if (err.response === undefined) { - err.response = response; - } - error(err); - return; - } - - success(response.data, response); - }, error); - }; - - var isBatch = function (value) { - /// <summary>Tests whether a value is a batch object in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <returns type="Boolean">True is the value is a batch object; false otherwise.</returns> - - return isComplex(value) && isArray(value.__batchRequests); - }; - - // Regular expression used for testing and parsing for a collection type. - var collectionTypeRE = /Collection\((.*)\)/; - - var isCollection = function (value, typeName) { - /// <summary>Tests whether a value is a collection value in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param> - /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns> - - var colData = value && value.results || value; - return !!colData && - (isCollectionType(typeName)) || - (!typeName && isArray(colData) && !isComplex(colData[0])); - }; - - var isCollectionType = function (typeName) { - /// <summary>Checks whether the specified type name is a collection type.</summary> - /// <param name="typeName" type="String">Name of type to check.</param> - /// <returns type="Boolean">True if the type is the name of a collection type; false otherwise.</returns> - return collectionTypeRE.test(typeName); - }; - - var isComplex = function (value) { - /// <summary>Tests whether a value is a complex type value in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <returns type="Boolean">True is the value is a complex type value; false otherwise.</returns> - - return !!value && - isObject(value) && - !isArray(value) && - !isDate(value); - }; - - var isDateTimeOffset = function (value) { - /// <summary>Checks whether a Date object is DateTimeOffset value</summary> - /// <param name="value" type="Date" mayBeNull="false">Value to check.</param> - /// <returns type="Boolean">true if the value is a DateTimeOffset, false otherwise.</returns> - return (value.__edmType === "Edm.DateTimeOffset" || (!value.__edmType && value.__offset)); - }; - - var isDeferred = function (value) { - /// <summary>Tests whether a value is a deferred navigation property in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <returns type="Boolean">True is the value is a deferred navigation property; false otherwise.</returns> - - if (!value && !isComplex(value)) { - return false; - } - var metadata = value.__metadata || {}; - var deferred = value.__deferred || {}; - return !metadata.type && !!deferred.uri; - }; - - var isEntry = function (value) { - /// <summary>Tests whether a value is an entry object in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <returns type="Boolean">True is the value is an entry object; false otherwise.</returns> - - return isComplex(value) && value.__metadata && "uri" in value.__metadata; - }; - - var isFeed = function (value, typeName) { - /// <summary>Tests whether a value is a feed value in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <param name="typeName" type="Sting">Type name of the value. This is used to disambiguate from a collection property value.</param> - /// <returns type="Boolean">True is the value is a feed value; false otherwise.</returns> - - var feedData = value && value.results || value; - return isArray(feedData) && ( - (!isCollectionType(typeName)) && - (isComplex(feedData[0])) - ); - }; - - var isGeographyEdmType = function (typeName) { - /// <summary>Checks whether the specified type name is a geography EDM type.</summary> - /// <param name="typeName" type="String">Name of type to check.</param> - /// <returns type="Boolean">True if the type is a geography EDM type; false otherwise.</returns> - - return contains(geographyEdmTypes, typeName); - }; - - var isGeometryEdmType = function (typeName) { - /// <summary>Checks whether the specified type name is a geometry EDM type.</summary> - /// <param name="typeName" type="String">Name of type to check.</param> - /// <returns type="Boolean">True if the type is a geometry EDM type; false otherwise.</returns> - - return contains(geometryEdmTypes, typeName); - }; - - var isNamedStream = function (value) { - /// <summary>Tests whether a value is a named stream value in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <returns type="Boolean">True is the value is a named stream; false otherwise.</returns> - - if (!value && !isComplex(value)) { - return false; - } - var metadata = value.__metadata; - var mediaResource = value.__mediaresource; - return !metadata && !!mediaResource && !!mediaResource.media_src; - }; - - var isPrimitive = function (value) { - /// <summary>Tests whether a value is a primitive type value in the library's internal representation.</summary> - /// <param name="value">Value to test.</param> - /// <remarks> - /// Date objects are considered primitive types by the library. - /// </remarks> - /// <returns type="Boolean">True is the value is a primitive type value.</returns> - - return isDate(value) || - typeof value === "string" || - typeof value === "number" || - typeof value === "boolean"; - }; - - var isPrimitiveEdmType = function (typeName) { - /// <summary>Checks whether the specified type name is a primitive EDM type.</summary> - /// <param name="typeName" type="String">Name of type to check.</param> - /// <returns type="Boolean">True if the type is a primitive EDM type; false otherwise.</returns> - - return contains(primitiveEdmTypes, typeName); - }; - - var navigationPropertyKind = function (value, propertyModel) { - /// <summary>Gets the kind of a navigation property value.</summary> - /// <param name="value">Value of the navigation property.</param> - /// <param name="propertyModel" type="Object" optional="true"> - /// Object that describes the navigation property in an OData conceptual schema. - /// </param> - /// <remarks> - /// The returned string is as follows - /// </remarks> - /// <returns type="String">String value describing the kind of the navigation property; null if the kind cannot be determined.</returns> - - if (isDeferred(value)) { - return "deferred"; - } - if (isEntry(value)) { - return "entry"; - } - if (isFeed(value)) { - return "feed"; - } - if (propertyModel && propertyModel.relationship) { - if (value === null || value === undefined || !isFeed(value)) { - return "entry"; - } - return "feed"; - } - return null; - }; - - var lookupProperty = function (properties, name) { - /// <summary>Looks up a property by name.</summary> - /// <param name="properties" type="Array" mayBeNull="true">Array of property objects as per EDM metadata.</param> - /// <param name="name" type="String">Name to look for.</param> - /// <returns type="Object">The property object; null if not found.</returns> - - return find(properties, function (property) { - return property.name === name; - }); - }; - - var lookupInMetadata = function (name, metadata, kind) { - /// <summary>Looks up a type object by name.</summary> - /// <param name="name" type="String">Name, possibly null or empty.</param> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <param name="kind" type="String">Kind of object to look for as per EDM metadata.</param> - /// <returns>An type description if the name is found; null otherwise.</returns> - - return (name) ? forEachSchema(metadata, function (schema) { - return lookupInSchema(name, schema, kind); - }) : null; - }; - - var lookupEntitySet = function (entitySets, name) { - /// <summary>Looks up a entity set by name.</summary> - /// <param name="properties" type="Array" mayBeNull="true">Array of entity set objects as per EDM metadata.</param> - /// <param name="name" type="String">Name to look for.</param> - /// <returns type="Object">The entity set object; null if not found.</returns> - - return find(entitySets, function (entitySet) { - return entitySet.name === name; - }); - }; - - var lookupComplexType = function (name, metadata) { - /// <summary>Looks up a complex type object by name.</summary> - /// <param name="name" type="String">Name, possibly null or empty.</param> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <returns>A complex type description if the name is found; null otherwise.</returns> - - return lookupInMetadata(name, metadata, "complexType"); - }; - - var lookupEntityType = function (name, metadata) { - /// <summary>Looks up an entity type object by name.</summary> - /// <param name="name" type="String">Name, possibly null or empty.</param> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <returns>An entity type description if the name is found; null otherwise.</returns> - - return lookupInMetadata(name, metadata, "entityType"); - }; - - var lookupDefaultEntityContainer = function (metadata) { - /// <summary>Looks up an</summary> - /// <param name="name" type="String">Name, possibly null or empty.</param> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <returns>An entity container description if the name is found; null otherwise.</returns> - - return forEachSchema(metadata, function (schema) { - return find(schema.entityContainer, function (container) { - return parseBool(container.isDefaultEntityContainer); - }); - }); - }; - - var lookupEntityContainer = function (name, metadata) { - /// <summary>Looks up an entity container object by name.</summary> - /// <param name="name" type="String">Name, possibly null or empty.</param> - /// <param name="metadata">Metadata store; one of edmx, schema, or an array of any of them.</param> - /// <returns>An entity container description if the name is found; null otherwise.</returns> - - return lookupInMetadata(name, metadata, "entityContainer"); - }; - - var lookupFunctionImport = function (functionImports, name) { - /// <summary>Looks up a function import by name.</summary> - /// <param name="properties" type="Array" mayBeNull="true">Array of function import objects as per EDM metadata.</param> - /// <param name="name" type="String">Name to look for.</param> - /// <returns type="Object">The entity set object; null if not found.</returns> - - return find(functionImports, function (functionImport) { - return functionImport.name === name; - }); - }; - - var lookupNavigationPropertyType = function (navigationProperty, metadata) { - /// <summary>Looks up the target entity type for a navigation property.</summary> - /// <param name="navigationProperty" type="Object"></param> - /// <param name="metadata" type="Object"></param> - /// <returns type="String">The entity type name for the specified property, null if not found.</returns> - - var result = null; - if (navigationProperty) { - var rel = navigationProperty.relationship; - var association = forEachSchema(metadata, function (schema) { - // The name should be the namespace qualified name in 'ns'.'type' format. - var nameOnly = removeNamespace(schema["namespace"], rel); - var associations = schema.association; - if (nameOnly && associations) { - var i, len; - for (i = 0, len = associations.length; i < len; i++) { - if (associations[i].name === nameOnly) { - return associations[i]; - } - } - } - return null; - }); - - if (association) { - var end = association.end[0]; - if (end.role !== navigationProperty.toRole) { - end = association.end[1]; - // For metadata to be valid, end.role === navigationProperty.toRole now. - } - result = end.type; - } - } - return result; - }; - - var lookupNavigationPropertyEntitySet = function (navigationProperty, sourceEntitySetName, metadata) { - /// <summary>Looks up the target entityset name for a navigation property.</summary> - /// <param name="navigationProperty" type="Object"></param> - /// <param name="metadata" type="Object"></param> - /// <returns type="String">The entityset name for the specified property, null if not found.</returns> - - if (navigationProperty) { - var rel = navigationProperty.relationship; - var associationSet = forEachSchema(metadata, function (schema) { - var containers = schema.entityContainer; - for (var i = 0; i < containers.length; i++) { - var associationSets = containers[i].associationSet; - if (associationSets) { - for (var j = 0; j < associationSets.length; j++) { - if (associationSets[j].association == rel) { - return associationSets[j]; - } - } - } - } - return null; - }); - if (associationSet && associationSet.end[0] && associationSet.end[1]) { - return (associationSet.end[0].entitySet == sourceEntitySetName) ? associationSet.end[1].entitySet : associationSet.end[0].entitySet; - } - } - return null; - }; - - var getEntitySetInfo = function (entitySetName, metadata) { - /// <summary>Gets the entitySet info, container name and functionImports for an entitySet</summary> - /// <param name="navigationProperty" type="Object"></param> - /// <param name="metadata" type="Object"></param> - /// <returns type="Object">The info about the entitySet.</returns> - - var info = forEachSchema(metadata, function (schema) { - var contai
<TRUNCATED>
