📄 microformats.js
字号:
/* when contained in hCard are a special case */ var parentnode; var node = propnodes[i]; var xpathExpression = ""; for (let j=0; j < Microformats.list.length; j++) { /* Don't treat adr or geo in an hCard as a microformat in this case */ if ((mfname == "hCard") && ((Microformats.list[j] == "adr") || (Microformats.list[j] == "geo"))) { continue; } if (Microformats[Microformats.list[j]].className) { if (xpathExpression.length == 0) { xpathExpression = "ancestor::*["; } else { xpathExpression += " or "; } xpathExpression += "contains(concat(' ', @class, ' '), ' " + Microformats[Microformats.list[j]].className + " ')"; } } xpathExpression += "][1]"; var xpathResult = (node.ownerDocument || node).evaluate(xpathExpression, node, null, Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null); if (xpathResult.singleNodeValue) { xpathResult.singleNodeValue.microformat = mfname; parentnode = xpathResult.singleNodeValue; } /* If the propnode is not a child of the microformat, and */ /* the property belongs to the parent microformat as well, */ /* remove it. */ if (parentnode != mfnode) { var mfNameString = Microformats.getNamesFromNode(parentnode); var mfNames = mfNameString.split(" "); var j; for (j=0; j < mfNames.length; j++) { /* If this property is in the parent microformat, remove the node */ if (Microformats[mfNames[j]].properties[propname]) { propnodes.splice(i,1);; break; } } } } if (propnodes.length > 0) { var resultArray = []; for (let i = 0; i < propnodes.length; i++) { var subresult = Microformats.parser.getPropertyInternal(propnodes[i], mfnode, propobj, propname); if (subresult != undefined) { resultArray.push(subresult); /* If we're not a plural property, don't bother getting more */ if (!propobj.plural) { return resultArray[0]; } } } if (resultArray.length > 0) { return resultArray; } } else { /* If we didn't find any class nodes, check to see if this property */ /* is virtual and if so, call getPropertyInternal again */ if (propobj.virtual) { return Microformats.parser.getPropertyInternal(mfnode, null, propobj, propname); } } return; }, /** * Internal parser API used to resolve includes and headers. Includes are * resolved by simply cloning the node and replacing it in a clone of the * original DOM node. Headers are resolved by creating a span and then copying * the innerHTML and the class name. * * @param in_mfnode The node to preProcess. * @return If the node had includes or headers, a cloned node otherwise * the original node. You can check to see if the node was cloned * by looking for .origNode in the new node. */ preProcessMicroformat: function preProcessMicroformat(in_mfnode) { var mfnode; var includes = Microformats.getElementsByClassName(in_mfnode, "include"); if ((includes.length > 0) || ((in_mfnode.nodeName.toLowerCase() == "td") && (in_mfnode.getAttribute("headers")))) { mfnode = in_mfnode.cloneNode(true); mfnode.origNode = in_mfnode; if (includes.length > 0) { includes = Microformats.getElementsByClassName(mfnode, "include"); var includeId; var include_length = includes.length; for (let i = include_length -1; i >= 0; i--) { if (includes[i].nodeName.toLowerCase() == "a") { includeId = includes[i].getAttribute("href").substr(1); } if (includes[i].nodeName.toLowerCase() == "object") { includeId = includes[i].getAttribute("data").substr(1); } if (in_mfnode.ownerDocument.getElementById(includeId)) { includes[i].parentNode.replaceChild(in_mfnode.ownerDocument.getElementById(includeId).cloneNode(true), includes[i]); } } } else { var headers = in_mfnode.getAttribute("headers").split(" "); for (let i = 0; i < headers.length; i++) { var tempNode = in_mfnode.ownerDocument.createElement("span"); var headerNode = in_mfnode.ownerDocument.getElementById(headers[i]); if (headerNode) { tempNode.innerHTML = headerNode.innerHTML; tempNode.className = headerNode.className; mfnode.appendChild(tempNode); } } } } else { mfnode = in_mfnode; } return mfnode; }, validate: function validate(mfnode, mfname) { var error = ""; if (Microformats[mfname].validate) { return Microformats[mfname].validate(mfnode); } else if (Microformats[mfname].required) { for (let i=0;i<Microformats[mfname].required.length;i++) { if (!Microformats.parser.getMicroformatProperty(mfnode, mfname, Microformats[mfname].required[i])) { error += "Required property " + Microformats[mfname].required[i] + " not specified\n"; } } if (error.length > 0) { throw(error); } return true; } }, /* This function normalizes an ISO8601 date by adding punctuation and */ /* ensuring that hours and seconds have values */ normalizeISO8601: function normalizeISO8601(string) { var dateArray = string.match(/(\d\d\d\d)(?:-?(\d\d)(?:-?(\d\d)(?:[T ](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(?:([-+Z])(?:(\d\d)(?::?(\d\d))?)?)?)?)?)?/); var dateString; var tzOffset = 0; if (!dateArray) { return; } if (dateArray[1]) { dateString = dateArray[1]; if (dateArray[2]) { dateString += "-" + dateArray[2]; if (dateArray[3]) { dateString += "-" + dateArray[3]; if (dateArray[4]) { dateString += "T" + dateArray[4]; if (dateArray[5]) { dateString += ":" + dateArray[5]; } else { dateString += ":" + "00"; } if (dateArray[6]) { dateString += ":" + dateArray[6]; } else { dateString += ":" + "00"; } if (dateArray[7]) { dateString += "." + dateArray[7]; } if (dateArray[8]) { dateString += dateArray[8]; if ((dateArray[8] == "+") || (dateArray[8] == "-")) { if (dateArray[9]) { dateString += dateArray[9]; if (dateArray[10]) { dateString += dateArray[10]; } } } } } } } } return dateString; } }, /** * Converts an ISO8601 date into a JavaScript date object, honoring the TZ * offset and Z if present to convert the date to local time * NOTE: I'm using an extra parameter on the date object for this function. * I set date.time to true if there is a date, otherwise date.time is false. * * @param string ISO8601 formatted date * @return JavaScript date object that represents the ISO date. */ dateFromISO8601: function dateFromISO8601(string) { var dateArray = string.match(/(\d\d\d\d)(?:-?(\d\d)(?:-?(\d\d)(?:[T ](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(?:([-+Z])(?:(\d\d)(?::?(\d\d))?)?)?)?)?)?/); var date = new Date(dateArray[1], 0, 1); date.time = false; if (dateArray[2]) { date.setMonth(dateArray[2] - 1); } if (dateArray[3]) { date.setDate(dateArray[3]); } if (dateArray[4]) { date.setHours(dateArray[4]); date.time = true; if (dateArray[5]) { date.setMinutes(dateArray[5]); if (dateArray[6]) { date.setSeconds(dateArray[6]); if (dateArray[7]) { date.setMilliseconds(Number("0." + dateArray[7]) * 1000); } } } } if (dateArray[8]) { if (dateArray[8] == "-") { if (dateArray[9] && dateArray[10]) { date.setHours(date.getHours() + parseInt(dateArray[9], 10)); date.setMinutes(date.getMinutes() + parseInt(dateArray[10], 10)); } } else if (dateArray[8] == "+") { if (dateArray[9] && dateArray[10]) { date.setHours(date.getHours() - parseInt(dateArray[9], 10)); date.setMinutes(date.getMinutes() - parseInt(dateArray[10], 10)); } } /* at this point we have the time in gmt */ /* convert to local if we had a Z - or + */ if (dateArray[8]) { var tzOffset = date.getTimezoneOffset(); if (tzOffset < 0) { date.setMinutes(date.getMinutes() + tzOffset); } else if (tzOffset > 0) { date.setMinutes(date.getMinutes() - tzOffset); } } } return date; }, /** * Converts a Javascript date object into an ISO 8601 formatted date * NOTE: I'm using an extra parameter on the date object for this function. * If date.time is NOT true, this function only outputs the date. * * @param date Javascript Date object * @param punctuation true if the date should have -/: * @return string with the ISO date. */ iso8601FromDate: function iso8601FromDate(date, punctuation) { var string = date.getFullYear().toString(); if (punctuation) { string += "-"; } string += (date.getMonth() + 1).toString().replace(/\b(\d)\b/g, '0$1'); if (punctuation) { string += "-"; } string += date.getDate().toString().replace(/\b(\d)\b/g, '0$1'); if (date.time) { string += "T"; string += date.getHours().toString().replace(/\b(\d)\b/g, '0$1'); if (punctuation) { string += ":"; } string += date.getMinutes().toString().replace(/\b(\d)\b/g, '0$1'); if (punctuation) { string += ":"; } string += date.getSeconds().toString().replace(/\b(\d)\b/g, '0$1'); if (date.getMilliseconds() > 0) { if (punctuation) { string += "."; } string += date.getMilliseconds().toString(); } } return string; }, simpleEscape: function simpleEscape(s) { s = s.replace(/\&/g, '%26'); s = s.replace(/\#/g, '%23'); s = s.replace(/\+/g, '%2B'); s = s.replace(/\-/g, '%2D'); s = s.replace(/\=/g, '%3D'); s = s.replace(/\'/g, '%27'); s = s.replace(/\,/g, '%2C');// s = s.replace(/\r/g, '%0D');// s = s.replace(/\n/g, '%0A'); s = s.replace(/ /g, '+'); return s; }, /** * Not intended for external consumption. Microformat implementations might use it. * * Retrieve elements matching all classes listed in a space-separated string. * I had to implement my own because I need an Array, not an nsIDomNodeList * * @param rootElement The DOM element at which to start searching (optional) * @param className A space separated list of classenames * @return microformatNodes An array of DOM Nodes, each representing a microformat in the document. */ getElementsByClassName: function getElementsByClassName(rootNode, className) { var returnElements = []; if ((rootNode.ownerDocument || rootNode).getElementsByClassName) { /* Firefox 3 - native getElementsByClassName */ var col = rootNode.getElementsByClassName(className); for (let i = 0; i < col.length; i++) { returnElements[i] = col[i]; } } else if ((rootNode.ownerDocument || rootNode).evaluate) { /* Firefox 2 and below - XPath */ var xpathExpression; xpathExpression = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; var xpathResult = (rootNode.ownerDocument || rootNode).evaluate(xpathExpression, rootNode, null, 0, null); var node; while (node = xpathResult.iterateNext()) { returnElements.push(node); } } else { /* Slow fallback for testing */ className = className.replace(/\-/g, "\\-"); var elements = rootNode.getElementsByTagName("*"); for (let i=0;i<elements.length;i++) { if (elements[i].className.match("(^|\\s)" + className + "(\\s|$)")) { returnElements.push(elements[i]); } } } return returnElements; }, /** * Not intended for external consumption. Microformat implementations might use it. * * Retrieve elements matching an attribute and an attribute list in a space-separated string. * * @param rootElement The DOM element at which to start searching (optional) * @param atributeName The attribute name to match against * @param attributeValues A space separated list of attribute values * @return microformatNodes An array of DOM Nodes, each representing a microformat in the document. */ getElementsByAttribute: function getElementsByAttribute(rootNode, attributeName, attributeValues) { var attributeList = attributeValues.split(" "); var returnElements = []; if ((rootNode.ownerDocument || rootNode).evaluate) { /* Firefox 3 and below - XPath */ /* Create an XPath expression based on the attribute list */ var xpathExpression = ".//*[";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -