?? microformats.js
字號:
var EXPORTED_SYMBOLS = ["Microformats", "adr", "tag", "hCard", "hCalendar", "geo"];var Microformats = { /* When a microformat is added, the name is placed in this list */ list: [], /* Custom iterator so that microformats can be enumerated as */ /* for (i in Microformats) */ __iterator__: function () { for (let i=0; i < this.list.length; i++) { yield this.list[i]; } }, /** * Retrieves microformats objects of the given type from a document * * @param name The name of the microformat (required) * @param rootElement The DOM element at which to start searching (required) * @param options Literal object with the following options: * recurseExternalFrames - Whether or not to search child frames * that reference external pages (with a src attribute) * for microformats (optional - defaults to true) * showHidden - Whether or not to add hidden microformat * (optional - defaults to false) * debug - Whether or not we are in debug mode (optional * - defaults to false) * @param targetArray An array of microformat objects to which is added the results (optional) * @return A new array of microformat objects or the passed in microformat * object array with the new objects added */ get: function(name, rootElement, options, targetArray) { function isAncestor(haystack, needle) { var parent = needle; while (parent = parent.parentNode) { /* We need to check parentNode because defaultView.frames[i].frameElement */ /* isn't a real DOM node */ if (parent == needle.parentNode) { return true; } } return false; } if (!Microformats[name] || !rootElement) { return; } targetArray = targetArray || []; /* Root element might not be the document - we need the document's default view */ /* to get frames and to check their ancestry */ var defaultView = rootElement.defaultView || rootElement.ownerDocument.defaultView; var rootDocument = rootElement.ownerDocument || rootElement; /* If recurseExternalFrames is undefined or true, look through all child frames for microformats */ if (!options || !options.hasOwnProperty("recurseExternalFrames") || options.recurseExternalFrames) { if (defaultView && defaultView.frames.length > 0) { for (let i=0; i < defaultView.frames.length; i++) { if (isAncestor(rootDocument, defaultView.frames[i].frameElement)) { Microformats.get(name, defaultView.frames[i].document, options, targetArray); } } } } /* Get the microformat nodes for the document */ var microformatNodes = []; if (Microformats[name].className) { microformatNodes = Microformats.getElementsByClassName(rootElement, Microformats[name].className); /* alternateClassName is for cases where a parent microformat is inferred by the children */ /* If we find alternateClassName, the entire document becomes the microformat */ if ((microformatNodes.length == 0) && Microformats[name].alternateClassName) { var altClass = Microformats.getElementsByClassName(rootElement, Microformats[name].alternateClassName); if (altClass.length > 0) { microformatNodes.push(rootElement); } } } else if (Microformats[name].attributeValues) { microformatNodes = Microformats.getElementsByAttribute(rootElement, Microformats[name].attributeName, Microformats[name].attributeValues); } /* Create objects for the microformat nodes and put them into the microformats */ /* array */ for (let i = 0; i < microformatNodes.length; i++) { /* If showHidden undefined or false, don't add microformats to the list that aren't visible */ if (!options || !options.hasOwnProperty("showHidden") || !options.showHidden) { if (microformatNodes[i].ownerDocument) { if (microformatNodes[i].getBoundingClientRect) { var box = microformatNodes[i].getBoundingClientRect(); box.width = box.right - box.left; box.height = box.bottom - box.top; } else { var box = microformatNodes[i].ownerDocument.getBoxObjectFor(microformatNodes[i]); } if ((box.height == 0) || (box.width == 0)) { continue; } } } try { if (options && options.debug) { /* Don't validate in the debug case so that we don't get errors thrown */ /* in the debug case, we want all microformats, even if they are invalid */ targetArray.push(new Microformats[name].mfObject(microformatNodes[i], false)); } else { targetArray.push(new Microformats[name].mfObject(microformatNodes[i], true)); } } catch (ex) { /* Creation of individual object probably failed because it is invalid. */ /* This isn't a problem, because the page might have invalid microformats */ } } return targetArray; }, /** * Counts microformats objects of the given type from a document * * @param name The name of the microformat (required) * @param rootElement The DOM element at which to start searching (required) * @param options Literal object with the following options: * recurseExternalFrames - Whether or not to search child frames * that reference external pages (with a src attribute) * for microformats (optional - defaults to true) * showHidden - Whether or not to add hidden microformat * (optional - defaults to false) * debug - Whether or not we are in debug mode (optional * - defaults to false) * @return The new count */ count: function(name, rootElement, options) { var mfArray = Microformats.get(name, rootElement, options); if (mfArray) { return mfArray.length; } return 0; }, /** * Returns true if the passed in node is a microformat. Does NOT return true * if the passed in node is a child of a microformat. * * @param node DOM node to check * @return true if the node is a microformat, false if it is not */ isMicroformat: function(node) { for (let i in Microformats) { if (Microformats[i].className) { if (Microformats.matchClass(node, Microformats[i].className)) { return true; } } else { var attribute; if (attribute = node.getAttribute(Microformats[i].attributeName)) { var attributeList = Microformats[i].attributeValues.split(" "); for (let j=0; j < attributeList.length; j++) { if (attribute.match("(^|\\s)" + attributeList[j] + "(\\s|$)")) { return true; } } } } } return false; }, /** * This function searches a given nodes ancestors looking for a microformat * and if it finds it, returns it. It does NOT include self, so if the passed * in node is a microformat, it will still search ancestors for a microformat. * * @param node DOM node to check * @return If the node is contained in a microformat, it returns the parent * DOM node, otherwise returns null */ getParent: function(node) { var xpathExpression; var xpathResult; xpathExpression = "ancestor::*["; for (let i=0; i < Microformats.list.length; i++) { var mfname = Microformats.list[i]; if (i != 0) { xpathExpression += " or "; } if (Microformats[mfname].className) { xpathExpression += "contains(concat(' ', @class, ' '), ' " + Microformats[mfname].className + " ')"; } else { var attributeList = Microformats[mfname].attributeValues.split(" "); for (let j=0; j < attributeList.length; j++) { if (j != 0) { xpathExpression += " or "; } xpathExpression += "contains(concat(' ', @" + Microformats[mfname].attributeName + ", ' '), ' " + attributeList[j] + " ')"; } } } xpathExpression += "][1]"; xpathResult = (node.ownerDocument || node).evaluate(xpathExpression, node, null, Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null); if (xpathResult.singleNodeValue) { xpathResult.singleNodeValue.microformat = mfname; return xpathResult.singleNodeValue; } return null; }, /** * If the passed in node is a microformat, this function returns a space * separated list of the microformat names that correspond to this node * * @param node DOM node to check * @return If the node is a microformat, a space separated list of microformat * names, otherwise returns nothing */ getNamesFromNode: function(node) { var microformatNames = []; var xpathExpression; var xpathResult; for (let i in Microformats) { if (Microformats[i]) { if (Microformats[i].className) { if (Microformats.matchClass(node, Microformats[i].className)) { microformatNames.push(i); continue; } } else if (Microformats[i].attributeValues) { var attribute; if (attribute = node.getAttribute(Microformats[i].attributeName)) { var attributeList = Microformats[i].attributeValues.split(" "); for (let j=0; j < attributeList.length; j++) { /* If we match any attribute, we've got a microformat */ if (attribute.match("(^|\\s)" + attributeList[j] + "(\\s|$)")) { microformatNames.push(i); break; } } } } } } return microformatNames.join(" "); }, /** * Outputs the contents of a microformat object for debug purposes. * * @param microformatObject JavaScript object that represents a microformat * @return string containing a visual representation of the contents of the microformat */ debug: function debug(microformatObject) { function dumpObject(item, indent) { if (!indent) { indent = ""; } var toreturn = ""; var testArray = []; for (let i in item) { if (testArray[i]) { continue; } if (typeof item[i] == "object") { if ((i != "node") && (i != "resolvedNode")) { if (item[i] && item[i].semanticType) { toreturn += indent + item[i].semanticType + " [" + i + "] { \n"; } else { toreturn += indent + "object " + i + " { \n"; } toreturn += dumpObject(item[i], indent + "\t"); toreturn += indent + "}\n"; } } else if ((typeof item[i] != "function") && (i != "semanticType")) { if (item[i]) { toreturn += indent + i + "=" + item[i] + "\n"; } } } if (!toreturn && item) { toreturn = item.toString(); } return toreturn; } return dumpObject(microformatObject); }, add: function add(microformat, microformatDefinition) { /* We always replace an existing definition with the new one */ if (!Microformats[microformat]) { Microformats.list.push(microformat); } Microformats[microformat] = microformatDefinition; microformatDefinition.mfObject.prototype.debug = function(microformatObject) { return Microformats.debug(microformatObject) }; }, /* All parser specific functions are contained in this object */ parser: { /** * Uses the microformat patterns to decide what the correct text for a * given microformat property is. This includes looking at things like * abbr, img/alt, area/alt and value excerpting. * * @param propnode The DOMNode to check * @param parentnode The parent node of the property. If it is a subproperty, * this is the parent property node. If it is not, this is the * microformat node. & @param datatype HTML/text - whether to use innerHTML or innerText - defaults to text * @return A string with the value of the property */ defaultGetter: function(propnode, parentnode, datatype) { if (((((propnode.localName.toLowerCase() == "abbr") || (propnode.localName.toLowerCase() == "html:abbr")) && !propnode.namespaceURI) || ((propnode.localName.toLowerCase() == "abbr") && (propnode.namespaceURI == "http://www.w3.org/1999/xhtml"))) && (propnode.getAttribute("title"))) { return propnode.getAttribute("title"); } else if ((propnode.nodeName.toLowerCase() == "img") && (propnode.getAttribute("alt"))) { return propnode.getAttribute("alt"); } else if ((propnode.nodeName.toLowerCase() == "area") && (propnode.getAttribute("alt"))) { return propnode.getAttribute("alt"); } else if ((propnode.nodeName.toLowerCase() == "textarea") || (propnode.nodeName.toLowerCase() == "select") || (propnode.nodeName.toLowerCase() == "input")) { return propnode.value; } else { var values = Microformats.getElementsByClassName(propnode, "value"); /* Verify that values are children of the propnode */ for (let i = values.length-1; i >= 0; i--) { if (values[i].parentNode != propnode) { values.splice(i,1); } } if (values.length > 0) { var value = ""; for (let j=0;j<values.length;j++) { value += Microformats.parser.defaultGetter(values[j], propnode, datatype); } return value; } var s; if (datatype == "HTML") { s = propnode.innerHTML; } else { if (propnode.innerText) { s = propnode.innerText; } else { s = propnode.textContent; } } /* If we are processing a value node, don't remove whitespace */ if (!Microformats.matchClass(propnode, "value")) { /* Remove new lines, carriage returns and tabs */ s = s.replace(/[\n\r\t]/gi, ' '); /* Replace any double spaces with single spaces */ s = s.replace(/\s{2,}/gi, ' '); /* Remove any double spaces that are left */ s = s.replace(/\s{2,}/gi, ''); /* Remove any spaces at the beginning */ s = s.replace(/^\s+/, ''); /* Remove any spaces at the end */ s = s.replace(/\s+$/, ''); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -