diff --git a/browser/base/content/browser-social.js b/browser/base/content/browser-social.js
index fac49738e0b4..ce1feba9c4a5 100644
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -639,17 +639,17 @@ SocialShare = {
}
this.sharePage(providerOrigin, pageData, target, anchor);
});
- gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData", null, { target });
+ gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData");
return;
}
- // if this is a share of a selected item, get any microformats
- if (!pageData.microformats && target) {
- messageManager.addMessageListener("PageMetadata:MicroformatsResult", _dataFn = (msg) => {
- messageManager.removeMessageListener("PageMetadata:MicroformatsResult", _dataFn);
- pageData.microformats = msg.data;
+ // if this is a share of a selected item, get any microdata
+ if (!pageData.microdata && target) {
+ messageManager.addMessageListener("PageMetadata:MicrodataResult", _dataFn = (msg) => {
+ messageManager.removeMessageListener("PageMetadata:MicrodataResult", _dataFn);
+ pageData.microdata = msg.data;
this.sharePage(providerOrigin, pageData, target, anchor);
});
- gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetMicroformats", null, { target });
+ gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetMicrodata", null, { target });
return;
}
this.currentShare = pageData;
diff --git a/browser/base/content/content.js b/browser/base/content/content.js
index 13c8a369ab53..74d8a1db8d81 100644
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -715,20 +715,20 @@ addEventListener("pageshow", function(event) {
var PageMetadataMessenger = {
init() {
addMessageListener("PageMetadata:GetPageData", this);
- addMessageListener("PageMetadata:GetMicroformats", this);
+ addMessageListener("PageMetadata:GetMicrodata", this);
},
receiveMessage(message) {
switch(message.name) {
case "PageMetadata:GetPageData": {
- let target = message.objects.target;
- let result = PageMetadata.getData(content.document, target);
+ let result = PageMetadata.getData(content.document);
sendAsyncMessage("PageMetadata:PageDataResult", result);
break;
}
- case "PageMetadata:GetMicroformats": {
+
+ case "PageMetadata:GetMicrodata": {
let target = message.objects.target;
- let result = PageMetadata.getMicroformats(content.document, target);
- sendAsyncMessage("PageMetadata:MicroformatsResult", result);
+ let result = PageMetadata.getMicrodata(content.document, target);
+ sendAsyncMessage("PageMetadata:MicrodataResult", result);
break;
}
}
diff --git a/browser/base/content/socialmarks.xml b/browser/base/content/socialmarks.xml
index 1c7fede9e0fc..72acca48cb6a 100644
--- a/browser/base/content/socialmarks.xml
+++ b/browser/base/content/socialmarks.xml
@@ -164,17 +164,17 @@
messageManager.removeMessageListener("PageMetadata:PageDataResult", _dataFn);
this.loadPanel(msg.json, target);
});
- gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData", null, { target });
+ gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData");
return;
}
- // if this is a share of a selected item, get any microformats
- if (!pageData.microformats && target) {
- messageManager.addMessageListener("PageMetadata:MicroformatsResult", _dataFn = (msg) => {
- messageManager.removeMessageListener("PageMetadata:MicroformatsResult", _dataFn);
- pageData.microformats = msg.data;
+ // if this is a share of a selected item, get any microdata
+ if (!pageData.microdata && target) {
+ messageManager.addMessageListener("PageMetadata:MicrodataResult", _dataFn = (msg) => {
+ messageManager.removeMessageListener("PageMetadata:MicrodataResult", _dataFn);
+ pageData.microdata = msg.data;
this.loadPanel(pageData, target);
});
- gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetMicroformats", null, { target });
+ gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetMicrodata", null, { target });
return;
}
this.pageData = pageData;
diff --git a/browser/base/content/test/social/browser.ini b/browser/base/content/test/social/browser.ini
index 7179b354cc69..0bd7f871bad0 100644
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -9,7 +9,7 @@ support-files =
opengraph/shortlink_linkrel.html
opengraph/shorturl_link.html
opengraph/shorturl_linkrel.html
- microformats.html
+ microdata.html
share.html
share_activate.html
social_activate.html
diff --git a/browser/base/content/test/social/browser_share.js b/browser/base/content/test/social/browser_share.js
index 2e0570d7bcfa..cac637d6a6c5 100644
--- a/browser/base/content/test/social/browser_share.js
+++ b/browser/base/content/test/social/browser_share.js
@@ -205,53 +205,53 @@ var tests = {
port.postMessage({topic: "test-init"});
executeSoon(runOneTest);
},
- testShareMicroformats: function(next) {
+ testShareMicrodata: function(next) {
SocialService.addProvider(manifest, function(provider) {
let port = provider.getWorkerPort();
let target, testTab;
let expecting = JSON.stringify({
- "url": "https://example.com/browser/browser/base/content/test/social/microformats.html",
- "title": "Raspberry Pi Page",
- "previews": ["https://example.com/someimage.jpg"],
- "microformats": {
+ "url": "https://example.com/browser/browser/base/content/test/social/microdata.html",
+ "title": "My Blog",
+ "previews": [],
+ "microdata": {
"items": [{
- "type": ["h-product"],
+ "types": ["http://schema.org/BlogPosting"],
"properties": {
- "name": ["Raspberry Pi"],
- "photo": ["https://example.com/someimage.jpg"],
- "description": [{
- "value": "The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.",
- "html": "The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming."
- }
- ],
- "url": ["https://example.com/"],
- "price": ["29.95"],
- "review": [{
- "value": "4.5 out of 5",
- "type": ["h-review"],
+ "headline": ["Progress report"],
+ "datePublished": ["2013-08-29"],
+ "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html?comments=0"],
+ "comment": [{
+ "types": ["http://schema.org/UserComments"],
"properties": {
- "rating": ["4.5"]
+ "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c1"],
+ "creator": [{
+ "types": ["http://schema.org/Person"],
+ "properties": {
+ "name": ["Greg"]
+ }
+ }
+ ],
+ "commentTime": ["2013-08-29"]
+ }
+ }, {
+ "types": ["http://schema.org/UserComments"],
+ "properties": {
+ "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"],
+ "creator": [{
+ "types": ["http://schema.org/Person"],
+ "properties": {
+ "name": ["Charlotte"]
+ }
+ }
+ ],
+ "commentTime": ["2013-08-29"]
}
}
- ],
- "category": ["Computer", "Education"]
+ ]
}
}
- ],
- "rels": {
- "tag": ["https://example.com/wiki/computer", "https://example.com/wiki/education"]
- },
- "rel-urls": {
- "https://example.com/wiki/computer": {
- "text": "Computer",
- "rels": ["tag"]
- },
- "https://example.com/wiki/education": {
- "text": "Education",
- "rels": ["tag"]
- }
- }
+ ]
}
});
@@ -259,15 +259,15 @@ var tests = {
let topic = e.data.topic;
switch (topic) {
case "got-share-data-message":
- is(JSON.stringify(e.data.result), expecting, "microformats data ok");
+ is(JSON.stringify(e.data.result), expecting, "microdata data ok");
gBrowser.removeTab(testTab);
SocialService.disableProvider(manifest.origin, next);
break;
}
}
port.postMessage({topic: "test-init"});
-
- let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
+
+ let url = "https://example.com/browser/browser/base/content/test/social/microdata.html"
addTab(url, function(tab) {
testTab = tab;
let doc = tab.linkedBrowser.contentDocument;
diff --git a/browser/base/content/test/social/browser_social_contextmenu.js b/browser/base/content/test/social/browser_social_contextmenu.js
index 54d6c7dc1bb1..305b6d24b3e3 100644
--- a/browser/base/content/test/social/browser_social_contextmenu.js
+++ b/browser/base/content/test/social/browser_social_contextmenu.js
@@ -27,26 +27,32 @@ function test() {
}
var tests = {
- testMarkMicroformats: function(next) {
+ testMarkMicrodata: function(next) {
// emulates context menu action using target element, calling SocialMarks.markLink
let provider = Social._getProviderFromOrigin(manifest.origin);
let port = provider.getWorkerPort();
let target, testTab;
- // browser_share tests microformats on the full page, this is testing a
+ // browser_share tests microdata on the full page, this is testing a
// specific target element.
let expecting = JSON.stringify({
- "url": "https://example.com/browser/browser/base/content/test/social/microformats.html",
- "microformats": {
+ "url": "https://example.com/browser/browser/base/content/test/social/microdata.html",
+ "microdata": {
"items": [{
- "type": ["h-review"],
+ "types": ["http://schema.org/UserComments"],
"properties": {
- "rating": ["4.5"]
+ "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"],
+ "creator": [{
+ "types": ["http://schema.org/Person"],
+ "properties": {
+ "name": ["Charlotte"]
+ }
+ }
+ ],
+ "commentTime": ["2013-08-29"]
}
}
- ],
- "rels": {},
- "rel-urls": {}
+ ]
}
});
@@ -54,7 +60,7 @@ var tests = {
let topic = e.data.topic;
switch (topic) {
case "got-share-data-message":
- is(JSON.stringify(e.data.result), expecting, "microformats data ok");
+ is(JSON.stringify(e.data.result), expecting, "microdata data ok");
gBrowser.removeTab(testTab);
port.close();
next();
@@ -63,11 +69,11 @@ var tests = {
}
port.postMessage({topic: "test-init"});
- let url = "https://example.com/browser/browser/base/content/test/social/microformats.html"
+ let url = "https://example.com/browser/browser/base/content/test/social/microdata.html"
addTab(url, function(tab) {
testTab = tab;
let doc = tab.linkedBrowser.contentDocument;
- target = doc.getElementById("test-review");
+ target = doc.getElementById("test-comment");
SocialMarks.markLink(manifest.origin, url, target);
});
}
diff --git a/browser/base/content/test/social/microdata.html b/browser/base/content/test/social/microdata.html
new file mode 100644
index 000000000000..f9222647a169
--- /dev/null
+++ b/browser/base/content/test/social/microdata.html
@@ -0,0 +1,38 @@
+
+
+My Blog
+
+
+
+
+ Progress report
+ today
+
+
+ All in all, he's doing well with his swim lessons. The biggest thing was he had trouble
+ putting his head in, but we got it down.
+
+ Comments
+
+
+
+ Posted by:
+ Greg
+
+ 15 minutes ago
+
+ Ha!
+
+
+
+
+
\ No newline at end of file
diff --git a/browser/base/content/test/social/microformats.html b/browser/base/content/test/social/microformats.html
deleted file mode 100644
index 3f04b61b76ed..000000000000
--- a/browser/base/content/test/social/microformats.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- Raspberry Pi Page
-
-
Raspberry Pi
-
-
The Raspberry Pi is a credit-card sized computer that plugs into your TV and a keyboard. It's a capable little PC which can be used for many of the things that your desktop PC does, like spreadsheets, word-processing and games. It also plays high-definition video. We want to see it being used by kids all over the world to learn programming.
-
More info about the Raspberry Pi
-
29.95
-
4.5 out of 5
-
Categories:
- Computer ,
- Education
-
-
-
-
diff --git a/testing/marionette/client/marionette/tests/unit-tests.ini b/testing/marionette/client/marionette/tests/unit-tests.ini
index e4ad450237ff..5786ad6835f5 100644
--- a/testing/marionette/client/marionette/tests/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit-tests.ini
@@ -20,6 +20,3 @@ test_container = true
; loop tests
[include:../../../../../browser/extensions/loop/manifest.ini]
-
-; microformats tests
-[include:../../../../../toolkit/components/microformats/manifest.ini]
diff --git a/toolkit/components/microformats/manifest.ini b/toolkit/components/microformats/manifest.ini
deleted file mode 100644
index 8eed4ea5cc03..000000000000
--- a/toolkit/components/microformats/manifest.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-b2g = false
-browser = true
-qemu = false
-
-[test/marionette/test_standards.py]
-[test/marionette/test_modules.py]
-[test/marionette/test_interface.py]
-
diff --git a/toolkit/components/microformats/microformat-shiv.js b/toolkit/components/microformats/microformat-shiv.js
deleted file mode 100644
index 7f05c6e2d144..000000000000
--- a/toolkit/components/microformats/microformat-shiv.js
+++ /dev/null
@@ -1,4548 +0,0 @@
-/*
- Modern
- microformat-shiv - v1.3.3
- Built: 2015-12-31 01:12 - http://microformat-shiv.com
- Copyright (c) 2015 Glenn Jones
- Licensed MIT
-*/
-
-
-var Microformats; // jshint ignore:line
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], factory);
- } else if (typeof exports === 'object') {
- module.exports = factory();
- } else {
- root.Microformats = factory();
- }
-}(this, function () {
-
- var modules = {};
-
-
- modules.version = '1.3.3';
- modules.livingStandard = '2015-09-25T12:26:04Z';
-
- /**
- * constructor
- *
- */
- modules.Parser = function () {
- this.rootPrefix = 'h-';
- this.propertyPrefixes = ['p-', 'dt-', 'u-', 'e-'];
- this.excludeTags = ['br', 'hr'];
- };
-
-
- // create objects incase the v1 map modules don't load
- modules.maps = (modules.maps)? modules.maps : {};
- modules.rels = (modules.rels)? modules.rels : {};
-
-
- modules.Parser.prototype = {
-
- init: function(){
- this.rootNode = null;
- this.document = null;
- this.options = {
- 'baseUrl': '',
- 'filters': [],
- 'textFormat': 'whitespacetrimmed',
- 'dateFormat': 'auto', // html5 for testing
- 'overlappingVersions': false,
- 'impliedPropertiesByVersion': true,
- 'parseLatLonGeo': false
- };
- this.rootID = 0;
- this.errors = [];
- this.noContentErr = 'No options.node or options.html was provided and no document object could be found.';
- },
-
-
- /**
- * internal parse function
- *
- * @param {Object} options
- * @return {Object}
- */
- get: function(options) {
- var out = this.formatEmpty(),
- data = [],
- rels;
-
- this.init();
- options = (options)? options : {};
- this.mergeOptions(options);
- this.getDOMContext( options );
-
- // if we do not have any context create error
- if(!this.rootNode || !this.document){
- this.errors.push(this.noContentErr);
- }else{
-
- // only parse h-* microformats if we need to
- // this is added to speed up parsing
- if(this.hasMicroformats(this.rootNode, options)){
- this.prepareDOM( options );
-
- if(this.options.filters.length > 0){
- // parse flat list of items
- var newRootNode = this.findFilterNodes(this.rootNode, this.options.filters);
- data = this.walkRoot(newRootNode);
- }else{
- // parse whole document from root
- data = this.walkRoot(this.rootNode);
- }
-
- out.items = data;
- // don't clear-up DOM if it was cloned
- if(modules.domUtils.canCloneDocument(this.document) === false){
- this.clearUpDom(this.rootNode);
- }
- }
-
- // find any rels
- if(this.findRels){
- rels = this.findRels(this.rootNode);
- out.rels = rels.rels;
- out['rel-urls'] = rels['rel-urls'];
- }
-
- }
-
- if(this.errors.length > 0){
- return this.formatError();
- }
- return out;
- },
-
-
- /**
- * parse to get parent microformat of passed node
- *
- * @param {DOM Node} node
- * @param {Object} options
- * @return {Object}
- */
- getParent: function(node, options) {
- this.init();
- options = (options)? options : {};
-
- if(node){
- return this.getParentTreeWalk(node, options);
- }else{
- this.errors.push(this.noContentErr);
- return this.formatError();
- }
- },
-
-
- /**
- * get the count of microformats
- *
- * @param {DOM Node} rootNode
- * @return {Int}
- */
- count: function( options ) {
- var out = {},
- items,
- classItems,
- x,
- i;
-
- this.init();
- options = (options)? options : {};
- this.getDOMContext( options );
-
- // if we do not have any context create error
- if(!this.rootNode || !this.document){
- return {'errors': [this.noContentErr]};
- }else{
-
- items = this.findRootNodes( this.rootNode, true );
- i = items.length;
- while(i--) {
- classItems = modules.domUtils.getAttributeList(items[i], 'class');
- x = classItems.length;
- while(x--) {
- // find v2 names
- if(modules.utils.startWith( classItems[x], 'h-' )){
- this.appendCount(classItems[x], 1, out);
- }
- // find v1 names
- for(var key in modules.maps) {
- // dont double count if v1 and v2 roots are present
- if(modules.maps[key].root === classItems[x] && classItems.indexOf(key) === -1) {
- this.appendCount(key, 1, out);
- }
- }
- }
- }
- var relCount = this.countRels( this.rootNode );
- if(relCount > 0){
- out.rels = relCount;
- }
-
- return out;
- }
- },
-
-
- /**
- * does a node have a class that marks it as a microformats root
- *
- * @param {DOM Node} node
- * @param {Objecte} options
- * @return {Boolean}
- */
- isMicroformat: function( node, options ) {
- var classes,
- i;
-
- if(!node){
- return false;
- }
-
- // if documemt gets topmost node
- node = modules.domUtils.getTopMostNode( node );
-
- // look for h-* microformats
- classes = this.getUfClassNames(node);
- if(options && options.filters && modules.utils.isArray(options.filters)){
- i = options.filters.length;
- while(i--) {
- if(classes.root.indexOf(options.filters[i]) > -1){
- return true;
- }
- }
- return false;
- }else{
- return (classes.root.length > 0);
- }
- },
-
-
- /**
- * does a node or its children have microformats
- *
- * @param {DOM Node} node
- * @param {Objecte} options
- * @return {Boolean}
- */
- hasMicroformats: function( node, options ) {
- var items,
- i;
-
- if(!node){
- return false;
- }
-
- // if browser based documemt get topmost node
- node = modules.domUtils.getTopMostNode( node );
-
- // returns all microformat roots
- items = this.findRootNodes( node, true );
- if(options && options.filters && modules.utils.isArray(options.filters)){
- i = items.length;
- while(i--) {
- if( this.isMicroformat( items[i], options ) ){
- return true;
- }
- }
- return false;
- }else{
- return (items.length > 0);
- }
- },
-
-
- /**
- * add a new v1 mapping object to parser
- *
- * @param {Array} maps
- */
- add: function( maps ){
- maps.forEach(function(map){
- if(map && map.root && map.name && map.properties){
- modules.maps[map.name] = JSON.parse(JSON.stringify(map));
- }
- });
- },
-
-
- /**
- * internal parse to get parent microformats by walking up the tree
- *
- * @param {DOM Node} node
- * @param {Object} options
- * @param {Int} recursive
- * @return {Object}
- */
- getParentTreeWalk: function (node, options, recursive) {
- options = (options)? options : {};
-
- // recursive calls
- if (recursive === undefined) {
- if (node.parentNode && node.nodeName !== 'HTML'){
- return this.getParentTreeWalk(node.parentNode, options, true);
- }else{
- return this.formatEmpty();
- }
- }
- if (node !== null && node !== undefined && node.parentNode) {
- if (this.isMicroformat( node, options )) {
- // if we have a match return microformat
- options.node = node;
- return this.get( options );
- }else{
- return this.getParentTreeWalk(node.parentNode, options, true);
- }
- }else{
- return this.formatEmpty();
- }
- },
-
-
-
- /**
- * configures what are the base DOM objects for parsing
- *
- * @param {Object} options
- */
- getDOMContext: function( options ){
- var nodes = modules.domUtils.getDOMContext( options );
- this.rootNode = nodes.rootNode;
- this.document = nodes.document;
- },
-
-
- /**
- * prepares DOM before the parse begins
- *
- * @param {Object} options
- * @return {Boolean}
- */
- prepareDOM: function( options ){
- var baseTag,
- href;
-
- // use current document to define baseUrl, try/catch needed for IE10+ error
- try {
- if (!options.baseUrl && this.document && this.document.location) {
- this.options.baseUrl = this.document.location.href;
- }
- } catch (e) {
- // there is no alt action
- }
-
-
- // find base tag to set baseUrl
- baseTag = modules.domUtils.querySelector(this.document,'base');
- if(baseTag) {
- href = modules.domUtils.getAttribute(baseTag, 'href');
- if(href){
- this.options.baseUrl = href;
- }
- }
-
- // get path to rootNode
- // then clone document
- // then reset the rootNode to its cloned version in a new document
- var path,
- newDocument,
- newRootNode;
-
- path = modules.domUtils.getNodePath(this.rootNode);
- newDocument = modules.domUtils.cloneDocument(this.document);
- newRootNode = modules.domUtils.getNodeByPath(newDocument, path);
-
- // check results as early IE fails
- if(newDocument && newRootNode){
- this.document = newDocument;
- this.rootNode = newRootNode;
- }
-
- // add includes
- if(this.addIncludes){
- this.addIncludes( this.document );
- }
-
- return (this.rootNode && this.document);
- },
-
-
- /**
- * returns an empty structure with errors
- *
- * @return {Object}
- */
- formatError: function(){
- var out = this.formatEmpty();
- out.errors = this.errors;
- return out;
- },
-
-
- /**
- * returns an empty structure
- *
- * @return {Object}
- */
- formatEmpty: function(){
- return {
- 'items': [],
- 'rels': {},
- 'rel-urls': {}
- };
- },
-
-
- // find microformats of a given type and return node structures
- findFilterNodes: function(rootNode, filters) {
- var newRootNode = modules.domUtils.createNode('div'),
- items = this.findRootNodes(rootNode, true),
- i = 0,
- x = 0,
- y = 0;
-
- if(items){
- i = items.length;
- while(x < i) {
- // add v1 names
- y = filters.length;
- while (y--) {
- if(this.getMapping(filters[y])){
- var v1Name = this.getMapping(filters[y]).root;
- filters.push(v1Name);
- }
- }
- // append matching nodes into newRootNode
- y = filters.length;
- while (y--) {
- if(modules.domUtils.hasAttributeValue(items[x], 'class', filters[y])){
- var clone = modules.domUtils.clone(items[x]);
- modules.domUtils.appendChild(newRootNode, clone);
- break;
- }
- }
- x++;
- }
- }
-
- return newRootNode;
- },
-
-
- /**
- * appends data to output object for count
- *
- * @param {string} name
- * @param {Int} count
- * @param {Object}
- */
- appendCount: function(name, count, out){
- if(out[name]){
- out[name] = out[name] + count;
- }else{
- out[name] = count;
- }
- },
-
-
- /**
- * is the microformats type in the filter list
- *
- * @param {Object} uf
- * @param {Array} filters
- * @return {Boolean}
- */
- shouldInclude: function(uf, filters) {
- var i;
-
- if(modules.utils.isArray(filters) && filters.length > 0) {
- i = filters.length;
- while(i--) {
- if(uf.type[0] === filters[i]) {
- return true;
- }
- }
- return false;
- } else {
- return true;
- }
- },
-
-
- /**
- * finds all microformat roots in a rootNode
- *
- * @param {DOM Node} rootNode
- * @param {Boolean} includeRoot
- * @return {Array}
- */
- findRootNodes: function(rootNode, includeRoot) {
- var arr = null,
- out = [],
- classList = [],
- items,
- x,
- i,
- y,
- key;
-
-
- // build an array of v1 root names
- for(key in modules.maps) {
- if (modules.maps.hasOwnProperty(key)) {
- classList.push(modules.maps[key].root);
- }
- }
-
- // get all elements that have a class attribute
- includeRoot = (includeRoot) ? includeRoot : false;
- if(includeRoot && rootNode.parentNode) {
- arr = modules.domUtils.getNodesByAttribute(rootNode.parentNode, 'class');
- } else {
- arr = modules.domUtils.getNodesByAttribute(rootNode, 'class');
- }
-
- // loop elements that have a class attribute
- x = 0;
- i = arr.length;
- while(x < i) {
-
- items = modules.domUtils.getAttributeList(arr[x], 'class');
-
- // loop classes on an element
- y = items.length;
- while(y--) {
- // match v1 root names
- if(classList.indexOf(items[y]) > -1) {
- out.push(arr[x]);
- break;
- }
-
- // match v2 root name prefix
- if(modules.utils.startWith(items[y], 'h-')) {
- out.push(arr[x]);
- break;
- }
- }
-
- x++;
- }
- return out;
- },
-
-
- /**
- * starts the tree walk to find microformats
- *
- * @param {DOM Node} node
- * @return {Array}
- */
- walkRoot: function(node){
- var context = this,
- children = [],
- child,
- classes,
- items = [],
- out = [];
-
- classes = this.getUfClassNames(node);
- // if it is a root microformat node
- if(classes && classes.root.length > 0){
- items = this.walkTree(node);
-
- if(items.length > 0){
- out = out.concat(items);
- }
- }else{
- // check if there are children and one of the children has a root microformat
- children = modules.domUtils.getChildren( node );
- if(children && children.length > 0 && this.findRootNodes(node, true).length > -1){
- for (var i = 0; i < children.length; i++) {
- child = children[i];
- items = context.walkRoot(child);
- if(items.length > 0){
- out = out.concat(items);
- }
- }
- }
- }
- return out;
- },
-
-
- /**
- * starts the tree walking for a single microformat
- *
- * @param {DOM Node} node
- * @return {Array}
- */
- walkTree: function(node) {
- var classes,
- out = [],
- obj,
- itemRootID;
-
- // loop roots found on one element
- classes = this.getUfClassNames(node);
- if(classes && classes.root.length && classes.root.length > 0){
-
- this.rootID++;
- itemRootID = this.rootID;
- obj = this.createUfObject(classes.root, classes.typeVersion);
-
- this.walkChildren(node, obj, classes.root, itemRootID, classes);
- if(this.impliedRules){
- this.impliedRules(node, obj, classes);
- }
- out.push( this.cleanUfObject(obj) );
-
-
- }
- return out;
- },
-
-
- /**
- * finds child properties of microformat
- *
- * @param {DOM Node} node
- * @param {Object} out
- * @param {String} ufName
- * @param {Int} rootID
- * @param {Object} parentClasses
- */
- walkChildren: function(node, out, ufName, rootID, parentClasses) {
- var context = this,
- children = [],
- rootItem,
- itemRootID,
- value,
- propertyName,
- propertyVersion,
- i,
- x,
- y,
- z,
- child;
-
- children = modules.domUtils.getChildren( node );
-
- y = 0;
- z = children.length;
- while(y < z) {
- child = children[y];
-
- // get microformat classes for this single element
- var classes = context.getUfClassNames(child, ufName);
-
- // a property which is a microformat
- if(classes.root.length > 0 && classes.properties.length > 0 && !child.addedAsRoot) {
- // create object with type, property and value
- rootItem = context.createUfObject(
- classes.root,
- classes.typeVersion,
- modules.text.parse(this.document, child, context.options.textFormat)
- );
-
- // add the microformat as an array of properties
- propertyName = context.removePropPrefix(classes.properties[0][0]);
-
- // modifies value with "implied value rule"
- if(parentClasses && parentClasses.root.length === 1 && parentClasses.properties.length === 1){
- if(context.impliedValueRule){
- out = context.impliedValueRule(out, parentClasses.properties[0][0], classes.properties[0][0], value);
- }
- }
-
- if(out.properties[propertyName]) {
- out.properties[propertyName].push(rootItem);
- } else {
- out.properties[propertyName] = [rootItem];
- }
-
- context.rootID++;
- // used to stop duplication in heavily nested structures
- child.addedAsRoot = true;
-
-
- x = 0;
- i = rootItem.type.length;
- itemRootID = context.rootID;
- while(x < i) {
- context.walkChildren(child, rootItem, rootItem.type, itemRootID, classes);
- x++;
- }
- if(this.impliedRules){
- context.impliedRules(child, rootItem, classes);
- }
- this.cleanUfObject(rootItem);
-
- }
-
- // a property which is NOT a microformat and has not been used for a given root element
- if(classes.root.length === 0 && classes.properties.length > 0) {
-
- x = 0;
- i = classes.properties.length;
- while(x < i) {
-
- value = context.getValue(child, classes.properties[x][0], out);
- propertyName = context.removePropPrefix(classes.properties[x][0]);
- propertyVersion = classes.properties[x][1];
-
- // modifies value with "implied value rule"
- if(parentClasses && parentClasses.root.length === 1 && parentClasses.properties.length === 1){
- if(context.impliedValueRule){
- out = context.impliedValueRule(out, parentClasses.properties[0][0], classes.properties[x][0], value);
- }
- }
-
- // if we have not added this value into a property with the same name already
- if(!context.hasRootID(child, rootID, propertyName)) {
- // check the root and property is the same version or if overlapping versions are allowed
- if( context.isAllowedPropertyVersion( out.typeVersion, propertyVersion ) ){
- // add the property as an array of properties
- if(out.properties[propertyName]) {
- out.properties[propertyName].push(value);
- } else {
- out.properties[propertyName] = [value];
- }
- // add rootid to node so we can track its use
- context.appendRootID(child, rootID, propertyName);
- }
- }
-
- x++;
- }
-
- context.walkChildren(child, out, ufName, rootID, classes);
- }
-
- // if the node has no microformat classes, see if its children have
- if(classes.root.length === 0 && classes.properties.length === 0) {
- context.walkChildren(child, out, ufName, rootID, classes);
- }
-
- // if the node is a child root add it to the children tree
- if(classes.root.length > 0 && classes.properties.length === 0) {
-
- // create object with type, property and value
- rootItem = context.createUfObject(
- classes.root,
- classes.typeVersion,
- modules.text.parse(this.document, child, context.options.textFormat)
- );
-
- // add the microformat as an array of properties
- if(!out.children){
- out.children = [];
- }
-
- if(!context.hasRootID(child, rootID, 'child-root')) {
- out.children.push( rootItem );
- context.appendRootID(child, rootID, 'child-root');
- context.rootID++;
- }
-
- x = 0;
- i = rootItem.type.length;
- itemRootID = context.rootID;
- while(x < i) {
- context.walkChildren(child, rootItem, rootItem.type, itemRootID, classes);
- x++;
- }
- if(this.impliedRules){
- context.impliedRules(child, rootItem, classes);
- }
- context.cleanUfObject( rootItem );
-
- }
-
-
-
- y++;
- }
-
- },
-
-
-
-
- /**
- * gets the value of a property from a node
- *
- * @param {DOM Node} node
- * @param {String} className
- * @param {Object} uf
- * @return {String || Object}
- */
- getValue: function(node, className, uf) {
- var value = '';
-
- if(modules.utils.startWith(className, 'p-')) {
- value = this.getPValue(node, true);
- }
-
- if(modules.utils.startWith(className, 'e-')) {
- value = this.getEValue(node);
- }
-
- if(modules.utils.startWith(className, 'u-')) {
- value = this.getUValue(node, true);
- }
-
- if(modules.utils.startWith(className, 'dt-')) {
- value = this.getDTValue(node, className, uf, true);
- }
- return value;
- },
-
-
- /**
- * gets the value of a node which contains a 'p-' property
- *
- * @param {DOM Node} node
- * @param {Boolean} valueParse
- * @return {String}
- */
- getPValue: function(node, valueParse) {
- var out = '';
- if(valueParse) {
- out = this.getValueClass(node, 'p');
- }
-
- if(!out && valueParse) {
- out = this.getValueTitle(node);
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['abbr'], 'title');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['data','input'], 'value');
- }
-
- if(node.name === 'br' || node.name === 'hr') {
- out = '';
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['img', 'area'], 'alt');
- }
-
- if(!out) {
- out = modules.text.parse(this.document, node, this.options.textFormat);
- }
-
- return(out) ? out : '';
- },
-
-
- /**
- * gets the value of a node which contains the 'e-' property
- *
- * @param {DOM Node} node
- * @return {Object}
- */
- getEValue: function(node) {
-
- var out = {value: '', html: ''};
-
- this.expandURLs(node, 'src', this.options.baseUrl);
- this.expandURLs(node, 'href', this.options.baseUrl);
-
- out.value = modules.text.parse(this.document, node, this.options.textFormat);
- out.html = modules.html.parse(node);
-
- return out;
- },
-
-
- /**
- * gets the value of a node which contains the 'u-' property
- *
- * @param {DOM Node} node
- * @param {Boolean} valueParse
- * @return {String}
- */
- getUValue: function(node, valueParse) {
- var out = '';
- if(valueParse) {
- out = this.getValueClass(node, 'u');
- }
-
- if(!out && valueParse) {
- out = this.getValueTitle(node);
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['a', 'area'], 'href');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['img','audio','video','source'], 'src');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['object'], 'data');
- }
-
- // if we have no protocol separator, turn relative url to absolute url
- if(out && out !== '' && out.indexOf('://') === -1) {
- out = modules.url.resolve(out, this.options.baseUrl);
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['abbr'], 'title');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['data','input'], 'value');
- }
-
- if(!out) {
- out = modules.text.parse(this.document, node, this.options.textFormat);
- }
-
- return(out) ? out : '';
- },
-
-
- /**
- * gets the value of a node which contains the 'dt-' property
- *
- * @param {DOM Node} node
- * @param {String} className
- * @param {Object} uf
- * @param {Boolean} valueParse
- * @return {String}
- */
- getDTValue: function(node, className, uf, valueParse) {
- var out = '';
-
- if(valueParse) {
- out = this.getValueClass(node, 'dt');
- }
-
- if(!out && valueParse) {
- out = this.getValueTitle(node);
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['time', 'ins', 'del'], 'datetime');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['abbr'], 'title');
- }
-
- if(!out) {
- out = modules.domUtils.getAttrValFromTagList(node, ['data', 'input'], 'value');
- }
-
- if(!out) {
- out = modules.text.parse(this.document, node, this.options.textFormat);
- }
-
- if(out) {
- if(modules.dates.isDuration(out)) {
- // just duration
- return out;
- } else if(modules.dates.isTime(out)) {
- // just time or time+timezone
- if(uf) {
- uf.times.push([className, modules.dates.parseAmPmTime(out, this.options.dateFormat)]);
- }
- return modules.dates.parseAmPmTime(out, this.options.dateFormat);
- } else {
- // returns a date - microformat profile
- if(uf) {
- uf.dates.push([className, new modules.ISODate(out).toString( this.options.dateFormat )]);
- }
- return new modules.ISODate(out).toString( this.options.dateFormat );
- }
- } else {
- return '';
- }
- },
-
-
- /**
- * appends a new rootid to a given node
- *
- * @param {DOM Node} node
- * @param {String} id
- * @param {String} propertyName
- */
- appendRootID: function(node, id, propertyName) {
- if(this.hasRootID(node, id, propertyName) === false){
- var rootids = [];
- if(modules.domUtils.hasAttribute(node,'rootids')){
- rootids = modules.domUtils.getAttributeList(node,'rootids');
- }
- rootids.push('id' + id + '-' + propertyName);
- modules.domUtils.setAttribute(node, 'rootids', rootids.join(' '));
- }
- },
-
-
- /**
- * does a given node already have a rootid
- *
- * @param {DOM Node} node
- * @param {String} id
- * @param {String} propertyName
- * @return {Boolean}
- */
- hasRootID: function(node, id, propertyName) {
- var rootids = [];
- if(!modules.domUtils.hasAttribute(node,'rootids')){
- return false;
- } else {
- rootids = modules.domUtils.getAttributeList(node, 'rootids');
- return (rootids.indexOf('id' + id + '-' + propertyName) > -1);
- }
- },
-
-
-
- /**
- * gets the text of any child nodes with a class value
- *
- * @param {DOM Node} node
- * @param {String} propertyName
- * @return {String || null}
- */
- getValueClass: function(node, propertyType) {
- var context = this,
- children = [],
- out = [],
- child,
- x,
- i;
-
- children = modules.domUtils.getChildren( node );
-
- x = 0;
- i = children.length;
- while(x < i) {
- child = children[x];
- var value = null;
- if(modules.domUtils.hasAttributeValue(child, 'class', 'value')) {
- switch(propertyType) {
- case 'p':
- value = context.getPValue(child, false);
- break;
- case 'u':
- value = context.getUValue(child, false);
- break;
- case 'dt':
- value = context.getDTValue(child, '', null, false);
- break;
- }
- if(value) {
- out.push(modules.utils.trim(value));
- }
- }
- x++;
- }
- if(out.length > 0) {
- if(propertyType === 'p') {
- return modules.text.parseText( this.document, out.join(' '), this.options.textFormat);
- }
- if(propertyType === 'u') {
- return out.join('');
- }
- if(propertyType === 'dt') {
- return modules.dates.concatFragments(out,this.options.dateFormat).toString(this.options.dateFormat);
- }
- } else {
- return null;
- }
- },
-
-
- /**
- * returns a single string of the 'title' attr from all
- * the child nodes with the class 'value-title'
- *
- * @param {DOM Node} node
- * @return {String}
- */
- getValueTitle: function(node) {
- var out = [],
- items,
- i,
- x;
-
- items = modules.domUtils.getNodesByAttributeValue(node, 'class', 'value-title');
- x = 0;
- i = items.length;
- while(x < i) {
- if(modules.domUtils.hasAttribute(items[x], 'title')) {
- out.push(modules.domUtils.getAttribute(items[x], 'title'));
- }
- x++;
- }
- return out.join('');
- },
-
-
- /**
- * finds out whether a node has h-* class v1 and v2
- *
- * @param {DOM Node} node
- * @return {Boolean}
- */
- hasHClass: function(node){
- var classes = this.getUfClassNames(node);
- if(classes.root && classes.root.length > 0){
- return true;
- }else{
- return false;
- }
- },
-
-
- /**
- * get both the root and property class names from a node
- *
- * @param {DOM Node} node
- * @param {Array} ufNameArr
- * @return {Object}
- */
- getUfClassNames: function(node, ufNameArr) {
- var context = this,
- out = {
- 'root': [],
- 'properties': []
- },
- classNames,
- key,
- items,
- item,
- i,
- x,
- z,
- y,
- map,
- prop,
- propName,
- v2Name,
- impiedRel,
- ufName;
-
- // don't get classes from excluded list of tags
- if(modules.domUtils.hasTagName(node, this.excludeTags) === false){
-
- // find classes for node
- classNames = modules.domUtils.getAttribute(node, 'class');
- if(classNames) {
- items = classNames.split(' ');
- x = 0;
- i = items.length;
- while(x < i) {
-
- item = modules.utils.trim(items[x]);
-
- // test for root prefix - v2
- if(modules.utils.startWith(item, context.rootPrefix)) {
- if(out.root.indexOf(item) === -1){
- out.root.push(item);
- }
- out.typeVersion = 'v2';
- }
-
- // test for property prefix - v2
- z = context.propertyPrefixes.length;
- while(z--) {
- if(modules.utils.startWith(item, context.propertyPrefixes[z])) {
- out.properties.push([item,'v2']);
- }
- }
-
- // test for mapped root classnames v1
- for(key in modules.maps) {
- if(modules.maps.hasOwnProperty(key)) {
- // only add a root once
- if(modules.maps[key].root === item && out.root.indexOf(key) === -1) {
- // if root map has subTree set to true
- // test to see if we should create a property or root
- if(modules.maps[key].subTree) {
- out.properties.push(['p-' + modules.maps[key].root, 'v1']);
- } else {
- out.root.push(key);
- if(!out.typeVersion){
- out.typeVersion = 'v1';
- }
- }
- }
- }
- }
-
-
- // test for mapped property classnames v1
- if(ufNameArr){
- for (var a = 0; a < ufNameArr.length; a++) {
- ufName = ufNameArr[a];
- // get mapped property v1 microformat
- map = context.getMapping(ufName);
- if(map) {
- for(key in map.properties) {
- if (map.properties.hasOwnProperty(key)) {
-
- prop = map.properties[key];
- propName = (prop.map) ? prop.map : 'p-' + key;
-
- if(key === item) {
- if(prop.uf) {
- // loop all the classList make sure
- // 1. this property is a root
- // 2. that there is not already an equivalent v2 property i.e. url and u-url on the same element
- y = 0;
- while(y < i) {
- v2Name = context.getV2RootName(items[y]);
- // add new root
- if(prop.uf.indexOf(v2Name) > -1 && out.root.indexOf(v2Name) === -1) {
- out.root.push(v2Name);
- out.typeVersion = 'v1';
- }
- y++;
- }
- //only add property once
- if(out.properties.indexOf(propName) === -1) {
- out.properties.push([propName,'v1']);
- }
- } else {
- if(out.properties.indexOf(propName) === -1) {
- out.properties.push([propName,'v1']);
- }
- }
- }
- }
-
- }
- }
- }
-
- }
-
- x++;
-
- }
- }
- }
-
-
- // finds any alt rel=* mappings for a given node/microformat
- if(ufNameArr && this.findRelImpied){
- for (var b = 0; b < ufNameArr.length; b++) {
- ufName = ufNameArr[b];
- impiedRel = this.findRelImpied(node, ufName);
- if(impiedRel && out.properties.indexOf(impiedRel) === -1) {
- out.properties.push([impiedRel, 'v1']);
- }
- }
- }
-
-
- //if(out.root.length === 1 && out.properties.length === 1) {
- // if(out.root[0].replace('h-','') === this.removePropPrefix(out.properties[0][0])) {
- // out.typeVersion = 'v2';
- // }
- //}
-
- return out;
- },
-
-
- /**
- * given a v1 or v2 root name, return mapping object
- *
- * @param {String} name
- * @return {Object || null}
- */
- getMapping: function(name) {
- var key;
- for(key in modules.maps) {
- if(modules.maps[key].root === name || key === name) {
- return modules.maps[key];
- }
- }
- return null;
- },
-
-
- /**
- * given a v1 root name returns a v2 root name i.e. vcard >>> h-card
- *
- * @param {String} name
- * @return {String || null}
- */
- getV2RootName: function(name) {
- var key;
- for(key in modules.maps) {
- if(modules.maps[key].root === name) {
- return key;
- }
- }
- return null;
- },
-
-
- /**
- * whether a property is the right microformats version for its root type
- *
- * @param {String} typeVersion
- * @param {String} propertyVersion
- * @return {Boolean}
- */
- isAllowedPropertyVersion: function(typeVersion, propertyVersion){
- if(this.options.overlappingVersions === true){
- return true;
- }else{
- return (typeVersion === propertyVersion);
- }
- },
-
-
- /**
- * creates a blank microformats object
- *
- * @param {String} name
- * @param {String} value
- * @return {Object}
- */
- createUfObject: function(names, typeVersion, value) {
- var out = {};
-
- // is more than just whitespace
- if(value && modules.utils.isOnlyWhiteSpace(value) === false) {
- out.value = value;
- }
- // add type i.e. ["h-card", "h-org"]
- if(modules.utils.isArray(names)) {
- out.type = names;
- } else {
- out.type = [names];
- }
- out.properties = {};
- // metadata properties for parsing
- out.typeVersion = typeVersion;
- out.times = [];
- out.dates = [];
- out.altValue = null;
-
- return out;
- },
-
-
- /**
- * removes unwanted microformats property before output
- *
- * @param {Object} microformat
- */
- cleanUfObject: function( microformat ) {
- delete microformat.times;
- delete microformat.dates;
- delete microformat.typeVersion;
- delete microformat.altValue;
- return microformat;
- },
-
-
-
- /**
- * removes microformat property prefixes from text
- *
- * @param {String} text
- * @return {String}
- */
- removePropPrefix: function(text) {
- var i;
-
- i = this.propertyPrefixes.length;
- while(i--) {
- var prefix = this.propertyPrefixes[i];
- if(modules.utils.startWith(text, prefix)) {
- text = text.substr(prefix.length);
- }
- }
- return text;
- },
-
-
- /**
- * expands all relative URLs to absolute ones where it can
- *
- * @param {DOM Node} node
- * @param {String} attrName
- * @param {String} baseUrl
- */
- expandURLs: function(node, attrName, baseUrl){
- var i,
- nodes,
- attr;
-
- nodes = modules.domUtils.getNodesByAttribute(node, attrName);
- i = nodes.length;
- while (i--) {
- try{
- // the url parser can blow up if the format is not right
- attr = modules.domUtils.getAttribute(nodes[i], attrName);
- if(attr && attr !== '' && baseUrl !== '' && attr.indexOf('://') === -1) {
- //attr = urlParser.resolve(baseUrl, attr);
- attr = modules.url.resolve(attr, baseUrl);
- modules.domUtils.setAttribute(nodes[i], attrName, attr);
- }
- }catch(err){
- // do nothing - convert only the urls we can, leave the rest as they are
- }
- }
- },
-
-
-
- /**
- * merges passed and default options -single level clone of properties
- *
- * @param {Object} options
- */
- mergeOptions: function(options) {
- var key;
- for(key in options) {
- if(options.hasOwnProperty(key)) {
- this.options[key] = options[key];
- }
- }
- },
-
-
- /**
- * removes all rootid attributes
- *
- * @param {DOM Node} rootNode
- */
- removeRootIds: function(rootNode){
- var arr,
- i;
-
- arr = modules.domUtils.getNodesByAttribute(rootNode, 'rootids');
- i = arr.length;
- while(i--) {
- modules.domUtils.removeAttribute(arr[i],'rootids');
- }
- },
-
-
- /**
- * removes all changes made to the DOM
- *
- * @param {DOM Node} rootNode
- */
- clearUpDom: function(rootNode){
- if(this.removeIncludes){
- this.removeIncludes(rootNode);
- }
- this.removeRootIds(rootNode);
- }
-
-
- };
-
-
- modules.Parser.prototype.constructor = modules.Parser;
-
-
- // check parser module is loaded
- if(modules.Parser){
-
- /**
- * applies "implied rules" microformat output structure i.e. feed-title, name, photo, url and date
- *
- * @param {DOM Node} node
- * @param {Object} uf (microformat output structure)
- * @param {Object} parentClasses (classes structure)
- * @param {Boolean} impliedPropertiesByVersion
- * @return {Object}
- */
- modules.Parser.prototype.impliedRules = function(node, uf, parentClasses) {
- var typeVersion = (uf.typeVersion)? uf.typeVersion: 'v2';
-
- // TEMP: override to allow v1 implied properties while spec changes
- if(this.options.impliedPropertiesByVersion === false){
- typeVersion = 'v2';
- }
-
- if(node && uf && uf.properties) {
- uf = this.impliedBackwardComp( node, uf, parentClasses );
- if(typeVersion === 'v2'){
- uf = this.impliedhFeedTitle( uf );
- uf = this.impliedName( node, uf );
- uf = this.impliedPhoto( node, uf );
- uf = this.impliedUrl( node, uf );
- }
- uf = this.impliedValue( node, uf, parentClasses );
- uf = this.impliedDate( uf );
-
- // TEMP: flagged while spec changes are put forward
- if(this.options.parseLatLonGeo === true){
- uf = this.impliedGeo( uf );
- }
- }
-
- return uf;
- };
-
-
- /**
- * apply implied name rule
- *
- * @param {DOM Node} node
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedName = function(node, uf) {
- // implied name rule
- /*
- img.h-x[alt]
- area.h-x[alt]
- abbr.h-x[title]
-
- .h-x>img:only-child[alt]:not[.h-*]
- .h-x>area:only-child[alt]:not[.h-*]
- .h-x>abbr:only-child[title]
-
- .h-x>:only-child>img:only-child[alt]:not[.h-*]
- .h-x>:only-child>area:only-child[alt]:not[.h-*]
- .h-x>:only-child>abbr:only-child[title]
- */
- var name,
- value;
-
- if(!uf.properties.name) {
- value = this.getImpliedProperty(node, ['img', 'area', 'abbr'], this.getNameAttr);
- var textFormat = this.options.textFormat;
- // if no value for tags/properties use text
- if(!value) {
- name = [modules.text.parse(this.document, node, textFormat)];
- }else{
- name = [modules.text.parseText(this.document, value, textFormat)];
- }
- if(name && name[0] !== ''){
- uf.properties.name = name;
- }
- }
-
- return uf;
- };
-
-
- /**
- * apply implied photo rule
- *
- * @param {DOM Node} node
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedPhoto = function(node, uf) {
- // implied photo rule
- /*
- img.h-x[src]
- object.h-x[data] Jane Doe
- .h-x>img[src]:only-of-type:not[.h-*]
- .h-x>object[data]:only-of-type:not[.h-*] Jane Doe
- .h-x>:only-child>img[src]:only-of-type:not[.h-*]
- .h-x>:only-child>object[data]:only-of-type:not[.h-*] Jane Doe
- */
- var value;
- if(!uf.properties.photo) {
- value = this.getImpliedProperty(node, ['img', 'object'], this.getPhotoAttr);
- if(value) {
- // relative to absolute URL
- if(value && value !== '' && this.options.baseUrl !== '' && value.indexOf('://') === -1) {
- value = modules.url.resolve(value, this.options.baseUrl);
- }
- uf.properties.photo = [modules.utils.trim(value)];
- }
- }
- return uf;
- };
-
-
- /**
- * apply implied URL rule
- *
- * @param {DOM Node} node
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedUrl = function(node, uf) {
- // implied URL rule
- /*
- a.h-x[href] Glenn
- area.h-x[href] Glenn
- .h-x>a[href]:only-of-type:not[.h-*]
- .h-x>area[href]:only-of-type:not[.h-*]
- */
- var value;
- if(!uf.properties.url) {
- value = this.getImpliedProperty(node, ['a', 'area'], this.getURLAttr);
- if(value) {
- // relative to absolute URL
- if(value && value !== '' && this.options.baseUrl !== '' && value.indexOf('://') === -1) {
- value = modules.url.resolve(value, this.options.baseUrl);
- }
- uf.properties.url = [modules.utils.trim(value)];
- }
- }
- return uf;
- };
-
-
- /**
- * apply implied date rule - if there is a time only property try to concat it with any date property
- *
- * @param {DOM Node} node
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedDate = function(uf) {
- // implied date rule
- // http://microformats.org/wiki/value-class-pattern#microformats2_parsers
- // http://microformats.org/wiki/microformats2-parsing-issues#implied_date_for_dt_properties_both_mf2_and_backcompat
- var newDate;
- if(uf.times.length > 0 && uf.dates.length > 0) {
- newDate = modules.dates.dateTimeUnion(uf.dates[0][1], uf.times[0][1], this.options.dateFormat);
- uf.properties[this.removePropPrefix(uf.times[0][0])][0] = newDate.toString(this.options.dateFormat);
- }
- // clean-up object
- delete uf.times;
- delete uf.dates;
- return uf;
- };
-
-
- /**
- * get an implied property value from pre-defined tag/attriubte combinations
- *
- * @param {DOM Node} node
- * @param {String} tagList (Array of tags from which an implied value can be pulled)
- * @param {String} getAttrFunction (Function which can extract implied value)
- * @return {String || null}
- */
- modules.Parser.prototype.getImpliedProperty = function(node, tagList, getAttrFunction) {
- // i.e. img.h-card
- var value = getAttrFunction(node),
- descendant,
- child;
-
- if(!value) {
- // i.e. .h-card>img:only-of-type:not(.h-card)
- descendant = modules.domUtils.getSingleDescendantOfType( node, tagList);
- if(descendant && this.hasHClass(descendant) === false){
- value = getAttrFunction(descendant);
- }
- if(node.children.length > 0 ){
- // i.e. .h-card>:only-child>img:only-of-type:not(.h-card)
- child = modules.domUtils.getSingleDescendant(node);
- if(child && this.hasHClass(child) === false){
- descendant = modules.domUtils.getSingleDescendantOfType(child, tagList);
- if(descendant && this.hasHClass(descendant) === false){
- value = getAttrFunction(descendant);
- }
- }
- }
- }
-
- return value;
- };
-
-
- /**
- * get an implied name value from a node
- *
- * @param {DOM Node} node
- * @return {String || null}
- */
- modules.Parser.prototype.getNameAttr = function(node) {
- var value = modules.domUtils.getAttrValFromTagList(node, ['img','area'], 'alt');
- if(!value) {
- value = modules.domUtils.getAttrValFromTagList(node, ['abbr'], 'title');
- }
- return value;
- };
-
-
- /**
- * get an implied photo value from a node
- *
- * @param {DOM Node} node
- * @return {String || null}
- */
- modules.Parser.prototype.getPhotoAttr = function(node) {
- var value = modules.domUtils.getAttrValFromTagList(node, ['img'], 'src');
- if(!value && modules.domUtils.hasAttributeValue(node, 'class', 'include') === false) {
- value = modules.domUtils.getAttrValFromTagList(node, ['object'], 'data');
- }
- return value;
- };
-
-
- /**
- * get an implied photo value from a node
- *
- * @param {DOM Node} node
- * @return {String || null}
- */
- modules.Parser.prototype.getURLAttr = function(node) {
- var value = null;
- if(modules.domUtils.hasAttributeValue(node, 'class', 'include') === false){
-
- value = modules.domUtils.getAttrValFromTagList(node, ['a'], 'href');
- if(!value) {
- value = modules.domUtils.getAttrValFromTagList(node, ['area'], 'href');
- }
-
- }
- return value;
- };
-
-
- /**
- *
- *
- * @param {DOM Node} node
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedValue = function(node, uf, parentClasses){
-
- // intersection of implied name and implied value rules
- if(uf.properties.name) {
- if(uf.value && parentClasses.root.length > 0 && parentClasses.properties.length === 1){
- uf = this.getAltValue(uf, parentClasses.properties[0][0], 'p-name', uf.properties.name[0]);
- }
- }
-
- // intersection of implied URL and implied value rules
- if(uf.properties.url) {
- if(parentClasses && parentClasses.root.length === 1 && parentClasses.properties.length === 1){
- uf = this.getAltValue(uf, parentClasses.properties[0][0], 'u-url', uf.properties.url[0]);
- }
- }
-
- // apply alt value
- if(uf.altValue !== null){
- uf.value = uf.altValue.value;
- }
- delete uf.altValue;
-
-
- return uf;
- };
-
-
- /**
- * get alt value based on rules about parent property prefix
- *
- * @param {Object} uf
- * @param {String} parentPropertyName
- * @param {String} propertyName
- * @param {String} value
- * @return {Object}
- */
- modules.Parser.prototype.getAltValue = function(uf, parentPropertyName, propertyName, value){
- if(uf.value && !uf.altValue){
- // first p-name of the h-* child
- if(modules.utils.startWith(parentPropertyName,'p-') && propertyName === 'p-name'){
- uf.altValue = {name: propertyName, value: value};
- }
- // if it's an e-* property element
- if(modules.utils.startWith(parentPropertyName,'e-') && modules.utils.startWith(propertyName,'e-')){
- uf.altValue = {name: propertyName, value: value};
- }
- // if it's an u-* property element
- if(modules.utils.startWith(parentPropertyName,'u-') && propertyName === 'u-url'){
- uf.altValue = {name: propertyName, value: value};
- }
- }
- return uf;
- };
-
-
- /**
- * if a h-feed does not have a title use the title tag of a page
- *
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedhFeedTitle = function( uf ){
- if(uf.type && uf.type.indexOf('h-feed') > -1){
- // has no name property
- if(uf.properties.name === undefined || uf.properties.name[0] === '' ){
- // use the text from the title tag
- var title = modules.domUtils.querySelector(this.document, 'title');
- if(title){
- uf.properties.name = [modules.domUtils.textContent(title)];
- }
- }
- }
- return uf;
- };
-
-
-
- /**
- * implied Geo from pattern
- *
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedGeo = function( uf ){
- var geoPair,
- parts,
- longitude,
- latitude,
- valid = true;
-
- if(uf.type && uf.type.indexOf('h-geo') > -1){
-
- // has no latitude or longitude property
- if(uf.properties.latitude === undefined || uf.properties.longitude === undefined ){
-
- geoPair = (uf.properties.name)? uf.properties.name[0] : null;
- geoPair = (!geoPair && uf.properties.value)? uf.properties.value : geoPair;
-
- if(geoPair){
- // allow for the use of a ';' as in microformats and also ',' as in Geo URL
- geoPair = geoPair.replace(';',',');
-
- // has sep char
- if(geoPair.indexOf(',') > -1 ){
- parts = geoPair.split(',');
-
- // only correct if we have two or more parts
- if(parts.length > 1){
-
- // latitude no value outside the range -90 or 90
- latitude = parseFloat( parts[0] );
- if(modules.utils.isNumber(latitude) && latitude > 90 || latitude < -90){
- valid = false;
- }
-
- // longitude no value outside the range -180 to 180
- longitude = parseFloat( parts[1] );
- if(modules.utils.isNumber(longitude) && longitude > 180 || longitude < -180){
- valid = false;
- }
-
- if(valid){
- uf.properties.latitude = [latitude];
- uf.properties.longitude = [longitude];
- }
- }
-
- }
- }
- }
- }
- return uf;
- };
-
-
- /**
- * if a backwards compat built structure has no properties add name through this.impliedName
- *
- * @param {Object} uf
- * @return {Object}
- */
- modules.Parser.prototype.impliedBackwardComp = function(node, uf, parentClasses){
-
- // look for pattern in parent classes like "p-geo h-geo"
- // these are structures built from backwards compat parsing of geo
- if(parentClasses.root.length === 1 && parentClasses.properties.length === 1) {
- if(parentClasses.root[0].replace('h-','') === this.removePropPrefix(parentClasses.properties[0][0])) {
-
- // if microformat has no properties apply the impliedName rule to get value from containing node
- // this will get value from html such as Brighton
- if( modules.utils.hasProperties(uf.properties) === false ){
- uf = this.impliedName( node, uf );
- }
- }
- }
-
- return uf;
- };
-
-
-
- }
-
-
- // check parser module is loaded
- if(modules.Parser){
-
-
- /**
- * appends clones of include Nodes into the DOM structure
- *
- * @param {DOM node} rootNode
- */
- modules.Parser.prototype.addIncludes = function(rootNode) {
- this.addAttributeIncludes(rootNode, 'itemref');
- this.addAttributeIncludes(rootNode, 'headers');
- this.addClassIncludes(rootNode);
- };
-
-
- /**
- * appends clones of include Nodes into the DOM structure for attribute based includes
- *
- * @param {DOM node} rootNode
- * @param {String} attributeName
- */
- modules.Parser.prototype.addAttributeIncludes = function(rootNode, attributeName) {
- var arr,
- idList,
- i,
- x,
- z,
- y;
-
- arr = modules.domUtils.getNodesByAttribute(rootNode, attributeName);
- x = 0;
- i = arr.length;
- while(x < i) {
- idList = modules.domUtils.getAttributeList(arr[x], attributeName);
- if(idList) {
- z = 0;
- y = idList.length;
- while(z < y) {
- this.apppendInclude(arr[x], idList[z]);
- z++;
- }
- }
- x++;
- }
- };
-
-
- /**
- * appends clones of include Nodes into the DOM structure for class based includes
- *
- * @param {DOM node} rootNode
- */
- modules.Parser.prototype.addClassIncludes = function(rootNode) {
- var id,
- arr,
- x = 0,
- i;
-
- arr = modules.domUtils.getNodesByAttributeValue(rootNode, 'class', 'include');
- i = arr.length;
- while(x < i) {
- id = modules.domUtils.getAttrValFromTagList(arr[x], ['a'], 'href');
- if(!id) {
- id = modules.domUtils.getAttrValFromTagList(arr[x], ['object'], 'data');
- }
- this.apppendInclude(arr[x], id);
- x++;
- }
- };
-
-
- /**
- * appends a clone of an include into another Node using Id
- *
- * @param {DOM node} rootNode
- * @param {Stringe} id
- */
- modules.Parser.prototype.apppendInclude = function(node, id){
- var include,
- clone;
-
- id = modules.utils.trim(id.replace('#', ''));
- include = modules.domUtils.getElementById(this.document, id);
- if(include) {
- clone = modules.domUtils.clone(include);
- this.markIncludeChildren(clone);
- modules.domUtils.appendChild(node, clone);
- }
- };
-
-
- /**
- * adds an attribute marker to all the child microformat roots
- *
- * @param {DOM node} rootNode
- */
- modules.Parser.prototype.markIncludeChildren = function(rootNode) {
- var arr,
- x,
- i;
-
- // loop the array and add the attribute
- arr = this.findRootNodes(rootNode);
- x = 0;
- i = arr.length;
- modules.domUtils.setAttribute(rootNode, 'data-include', 'true');
- modules.domUtils.setAttribute(rootNode, 'style', 'display:none');
- while(x < i) {
- modules.domUtils.setAttribute(arr[x], 'data-include', 'true');
- x++;
- }
- };
-
-
- /**
- * removes all appended include clones from DOM
- *
- * @param {DOM node} rootNode
- */
- modules.Parser.prototype.removeIncludes = function(rootNode){
- var arr,
- i;
-
- // remove all the items that were added as includes
- arr = modules.domUtils.getNodesByAttribute(rootNode, 'data-include');
- i = arr.length;
- while(i--) {
- modules.domUtils.removeChild(rootNode,arr[i]);
- }
- };
-
-
- }
-
-
- // check parser module is loaded
- if(modules.Parser){
-
- /**
- * finds rel=* structures
- *
- * @param {DOM node} rootNode
- * @return {Object}
- */
- modules.Parser.prototype.findRels = function(rootNode) {
- var out = {
- 'items': [],
- 'rels': {},
- 'rel-urls': {}
- },
- x,
- i,
- y,
- z,
- relList,
- items,
- item,
- value,
- arr;
-
- arr = modules.domUtils.getNodesByAttribute(rootNode, 'rel');
- x = 0;
- i = arr.length;
- while(x < i) {
- relList = modules.domUtils.getAttribute(arr[x], 'rel');
-
- if(relList) {
- items = relList.split(' ');
-
-
- // add rels
- z = 0;
- y = items.length;
- while(z < y) {
- item = modules.utils.trim(items[z]);
-
- // get rel value
- value = modules.domUtils.getAttrValFromTagList(arr[x], ['a', 'area'], 'href');
- if(!value) {
- value = modules.domUtils.getAttrValFromTagList(arr[x], ['link'], 'href');
- }
-
- // create the key
- if(!out.rels[item]) {
- out.rels[item] = [];
- }
-
- if(typeof this.options.baseUrl === 'string' && typeof value === 'string') {
-
- var resolved = modules.url.resolve(value, this.options.baseUrl);
- // do not add duplicate rels - based on resolved URLs
- if(out.rels[item].indexOf(resolved) === -1){
- out.rels[item].push( resolved );
- }
- }
- z++;
- }
-
-
- var url = null;
- if(modules.domUtils.hasAttribute(arr[x], 'href')){
- url = modules.domUtils.getAttribute(arr[x], 'href');
- if(url){
- url = modules.url.resolve(url, this.options.baseUrl );
- }
- }
-
-
- // add to rel-urls
- var relUrl = this.getRelProperties(arr[x]);
- relUrl.rels = items;
- // // do not add duplicate rel-urls - based on resolved URLs
- if(url && out['rel-urls'][url] === undefined){
- out['rel-urls'][url] = relUrl;
- }
-
-
- }
- x++;
- }
- return out;
- };
-
-
- /**
- * gets the properties of a rel=*
- *
- * @param {DOM node} node
- * @return {Object}
- */
- modules.Parser.prototype.getRelProperties = function(node){
- var obj = {};
-
- if(modules.domUtils.hasAttribute(node, 'media')){
- obj.media = modules.domUtils.getAttribute(node, 'media');
- }
- if(modules.domUtils.hasAttribute(node, 'type')){
- obj.type = modules.domUtils.getAttribute(node, 'type');
- }
- if(modules.domUtils.hasAttribute(node, 'hreflang')){
- obj.hreflang = modules.domUtils.getAttribute(node, 'hreflang');
- }
- if(modules.domUtils.hasAttribute(node, 'title')){
- obj.title = modules.domUtils.getAttribute(node, 'title');
- }
- if(modules.utils.trim(this.getPValue(node, false)) !== ''){
- obj.text = this.getPValue(node, false);
- }
-
- return obj;
- };
-
-
- /**
- * finds any alt rel=* mappings for a given node/microformat
- *
- * @param {DOM node} node
- * @param {String} ufName
- * @return {String || undefined}
- */
- modules.Parser.prototype.findRelImpied = function(node, ufName) {
- var out,
- map,
- i;
-
- map = this.getMapping(ufName);
- if(map) {
- for(var key in map.properties) {
- if (map.properties.hasOwnProperty(key)) {
- var prop = map.properties[key],
- propName = (prop.map) ? prop.map : 'p-' + key,
- relCount = 0;
-
- // is property an alt rel=* mapping
- if(prop.relAlt && modules.domUtils.hasAttribute(node, 'rel')) {
- i = prop.relAlt.length;
- while(i--) {
- if(modules.domUtils.hasAttributeValue(node, 'rel', prop.relAlt[i])) {
- relCount++;
- }
- }
- if(relCount === prop.relAlt.length) {
- out = propName;
- }
- }
- }
- }
- }
- return out;
- };
-
-
- /**
- * returns whether a node or its children has rel=* microformat
- *
- * @param {DOM node} node
- * @return {Boolean}
- */
- modules.Parser.prototype.hasRel = function(node) {
- return (this.countRels(node) > 0);
- };
-
-
- /**
- * returns the number of rel=* microformats
- *
- * @param {DOM node} node
- * @return {Int}
- */
- modules.Parser.prototype.countRels = function(node) {
- if(node){
- return modules.domUtils.getNodesByAttribute(node, 'rel').length;
- }
- return 0;
- };
-
-
-
- }
-
-
- modules.utils = {
-
- /**
- * is the object a string
- *
- * @param {Object} obj
- * @return {Boolean}
- */
- isString: function( obj ) {
- return typeof( obj ) === 'string';
- },
-
- /**
- * is the object a number
- *
- * @param {Object} obj
- * @return {Boolean}
- */
- isNumber: function( obj ) {
- return !isNaN(parseFloat( obj )) && isFinite( obj );
- },
-
-
- /**
- * is the object an array
- *
- * @param {Object} obj
- * @return {Boolean}
- */
- isArray: function( obj ) {
- return obj && !( obj.propertyIsEnumerable( 'length' ) ) && typeof obj === 'object' && typeof obj.length === 'number';
- },
-
-
- /**
- * is the object a function
- *
- * @param {Object} obj
- * @return {Boolean}
- */
- isFunction: function(obj) {
- return !!(obj && obj.constructor && obj.call && obj.apply);
- },
-
-
- /**
- * does the text start with a test string
- *
- * @param {String} text
- * @param {String} test
- * @return {Boolean}
- */
- startWith: function( text, test ) {
- return(text.indexOf(test) === 0);
- },
-
-
- /**
- * removes spaces at front and back of text
- *
- * @param {String} text
- * @return {String}
- */
- trim: function( text ) {
- if(text && this.isString(text)){
- return (text.trim())? text.trim() : text.replace(/^\s+|\s+$/g, '');
- }else{
- return '';
- }
- },
-
-
- /**
- * replaces a character in text
- *
- * @param {String} text
- * @param {Int} index
- * @param {String} character
- * @return {String}
- */
- replaceCharAt: function( text, index, character ) {
- if(text && text.length > index){
- return text.substr(0, index) + character + text.substr(index+character.length);
- }else{
- return text;
- }
- },
-
-
- /**
- * removes whitespace, tabs and returns from start and end of text
- *
- * @param {String} text
- * @return {String}
- */
- trimWhitespace: function( text ){
- if(text && text.length){
- var i = text.length,
- x = 0;
-
- // turn all whitespace chars at end into spaces
- while (i--) {
- if(this.isOnlyWhiteSpace(text[i])){
- text = this.replaceCharAt( text, i, ' ' );
- }else{
- break;
- }
- }
-
- // turn all whitespace chars at start into spaces
- i = text.length;
- while (x < i) {
- if(this.isOnlyWhiteSpace(text[x])){
- text = this.replaceCharAt( text, i, ' ' );
- }else{
- break;
- }
- x++;
- }
- }
- return this.trim(text);
- },
-
-
- /**
- * does text only contain whitespace characters
- *
- * @param {String} text
- * @return {Boolean}
- */
- isOnlyWhiteSpace: function( text ){
- return !(/[^\t\n\r ]/.test( text ));
- },
-
-
- /**
- * removes whitespace from text (leaves a single space)
- *
- * @param {String} text
- * @return {Sring}
- */
- collapseWhiteSpace: function( text ){
- return text.replace(/[\t\n\r ]+/g, ' ');
- },
-
-
- /**
- * does an object have any of its own properties
- *
- * @param {Object} obj
- * @return {Boolean}
- */
- hasProperties: function( obj ) {
- var key;
- for(key in obj) {
- if( obj.hasOwnProperty( key ) ) {
- return true;
- }
- }
- return false;
- },
-
-
- /**
- * a sort function - to sort objects in an array by a given property
- *
- * @param {String} property
- * @param {Boolean} reverse
- * @return {Int}
- */
- sortObjects: function(property, reverse) {
- reverse = (reverse) ? -1 : 1;
- return function (a, b) {
- a = a[property];
- b = b[property];
- if (a < b) {
- return reverse * -1;
- }
- if (a > b) {
- return reverse * 1;
- }
- return 0;
- };
- }
-
- };
-
-
- modules.domUtils = {
-
- // blank objects for DOM
- document: null,
- rootNode: null,
-
-
- /**
- * gets DOMParser object
- *
- * @return {Object || undefined}
- */
- getDOMParser: function () {
- if (typeof DOMParser === undefined) {
- try {
- return Components.classes["@mozilla.org/xmlextras/domparser;1"]
- .createInstance(Components.interfaces.nsIDOMParser);
- } catch (e) {
- return;
- }
- } else {
- return new DOMParser();
- }
- },
-
-
- /**
- * configures what are the base DOM objects for parsing
- *
- * @param {Object} options
- * @return {DOM Node} node
- */
- getDOMContext: function( options ){
-
- // if a node is passed
- if(options.node){
- this.rootNode = options.node;
- }
-
-
- // if a html string is passed
- if(options.html){
- //var domParser = new DOMParser();
- var domParser = this.getDOMParser();
- this.rootNode = domParser.parseFromString( options.html, 'text/html' );
- }
-
-
- // find top level document from rootnode
- if(this.rootNode !== null){
- if(this.rootNode.nodeType === 9){
- this.document = this.rootNode;
- this.rootNode = modules.domUtils.querySelector(this.rootNode, 'html');
- }else{
- // if it's DOM node get parent DOM Document
- this.document = modules.domUtils.ownerDocument(this.rootNode);
- }
- }
-
-
- // use global document object
- if(!this.rootNode && document){
- this.rootNode = modules.domUtils.querySelector(document, 'html');
- this.document = document;
- }
-
-
- if(this.rootNode && this.document){
- return {document: this.document, rootNode: this.rootNode};
- }
-
- return {document: null, rootNode: null};
- },
-
-
-
- /**
- * gets the first DOM node
- *
- * @param {Dom Document}
- * @return {DOM Node} node
- */
- getTopMostNode: function( node ){
- //var doc = this.ownerDocument(node);
- //if(doc && doc.nodeType && doc.nodeType === 9 && doc.documentElement){
- // return doc.documentElement;
- //}
- return node;
- },
-
-
-
- /**
- * abstracts DOM ownerDocument
- *
- * @param {DOM Node} node
- * @return {Dom Document}
- */
- ownerDocument: function(node){
- return node.ownerDocument;
- },
-
-
- /**
- * abstracts DOM textContent
- *
- * @param {DOM Node} node
- * @return {String}
- */
- textContent: function(node){
- if(node.textContent){
- return node.textContent;
- }else if(node.innerText){
- return node.innerText;
- }
- return '';
- },
-
-
- /**
- * abstracts DOM innerHTML
- *
- * @param {DOM Node} node
- * @return {String}
- */
- innerHTML: function(node){
- return node.innerHTML;
- },
-
-
- /**
- * abstracts DOM hasAttribute
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @return {Boolean}
- */
- hasAttribute: function(node, attributeName) {
- return node.hasAttribute(attributeName);
- },
-
-
- /**
- * does an attribute contain a value
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @param {String} value
- * @return {Boolean}
- */
- hasAttributeValue: function(node, attributeName, value) {
- return (this.getAttributeList(node, attributeName).indexOf(value) > -1);
- },
-
-
- /**
- * abstracts DOM getAttribute
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @return {String || null}
- */
- getAttribute: function(node, attributeName) {
- return node.getAttribute(attributeName);
- },
-
-
- /**
- * abstracts DOM setAttribute
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @param {String} attributeValue
- */
- setAttribute: function(node, attributeName, attributeValue){
- node.setAttribute(attributeName, attributeValue);
- },
-
-
- /**
- * abstracts DOM removeAttribute
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- */
- removeAttribute: function(node, attributeName) {
- node.removeAttribute(attributeName);
- },
-
-
- /**
- * abstracts DOM getElementById
- *
- * @param {DOM Node || DOM Document} node
- * @param {String} id
- * @return {DOM Node}
- */
- getElementById: function(docNode, id) {
- return docNode.querySelector( '#' + id );
- },
-
-
- /**
- * abstracts DOM querySelector
- *
- * @param {DOM Node || DOM Document} node
- * @param {String} selector
- * @return {DOM Node}
- */
- querySelector: function(docNode, selector) {
- return docNode.querySelector( selector );
- },
-
-
- /**
- * get value of a Node attribute as an array
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @return {Array}
- */
- getAttributeList: function(node, attributeName) {
- var out = [],
- attList;
-
- attList = node.getAttribute(attributeName);
- if(attList && attList !== '') {
- if(attList.indexOf(' ') > -1) {
- out = attList.split(' ');
- } else {
- out.push(attList);
- }
- }
- return out;
- },
-
-
- /**
- * gets all child nodes with a given attribute
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @return {NodeList}
- */
- getNodesByAttribute: function(node, attributeName) {
- var selector = '[' + attributeName + ']';
- return node.querySelectorAll(selector);
- },
-
-
- /**
- * gets all child nodes with a given attribute containing a given value
- *
- * @param {DOM Node} node
- * @param {String} attributeName
- * @return {DOM NodeList}
- */
- getNodesByAttributeValue: function(rootNode, name, value) {
- var arr = [],
- x = 0,
- i,
- out = [];
-
- arr = this.getNodesByAttribute(rootNode, name);
- if(arr) {
- i = arr.length;
- while(x < i) {
- if(this.hasAttributeValue(arr[x], name, value)) {
- out.push(arr[x]);
- }
- x++;
- }
- }
- return out;
- },
-
-
- /**
- * gets attribute value from controlled list of tags
- *
- * @param {Array} tagNames
- * @param {String} attributeName
- * @return {String || null}
- */
- getAttrValFromTagList: function(node, tagNames, attributeName) {
- var i = tagNames.length;
-
- while(i--) {
- if(node.tagName.toLowerCase() === tagNames[i]) {
- var attrValue = this.getAttribute(node, attributeName);
- if(attrValue && attrValue !== '') {
- return attrValue;
- }
- }
- }
- return null;
- },
-
-
- /**
- * get node if it has no siblings. CSS equivalent is :only-child
- *
- * @param {DOM Node} rootNode
- * @param {Array} tagNames
- * @return {DOM Node || null}
- */
- getSingleDescendant: function(node){
- return this.getDescendant( node, null, false );
- },
-
-
- /**
- * get node if it has no siblings of the same type. CSS equivalent is :only-of-type
- *
- * @param {DOM Node} rootNode
- * @param {Array} tagNames
- * @return {DOM Node || null}
- */
- getSingleDescendantOfType: function(node, tagNames){
- return this.getDescendant( node, tagNames, true );
- },
-
-
- /**
- * get child node limited by presence of siblings - either CSS :only-of-type or :only-child
- *
- * @param {DOM Node} rootNode
- * @param {Array} tagNames
- * @return {DOM Node || null}
- */
- getDescendant: function( node, tagNames, onlyOfType ){
- var i = node.children.length,
- countAll = 0,
- countOfType = 0,
- child,
- out = null;
-
- while(i--) {
- child = node.children[i];
- if(child.nodeType === 1) {
- if(tagNames){
- // count just only-of-type
- if(this.hasTagName(child, tagNames)){
- out = child;
- countOfType++;
- }
- }else{
- // count all elements
- out = child;
- countAll++;
- }
- }
- }
- if(onlyOfType === true){
- return (countOfType === 1)? out : null;
- }else{
- return (countAll === 1)? out : null;
- }
- },
-
-
- /**
- * is a node one of a list of tags
- *
- * @param {DOM Node} rootNode
- * @param {Array} tagNames
- * @return {Boolean}
- */
- hasTagName: function(node, tagNames){
- var i = tagNames.length;
- while(i--) {
- if(node.tagName.toLowerCase() === tagNames[i]) {
- return true;
- }
- }
- return false;
- },
-
-
- /**
- * abstracts DOM appendChild
- *
- * @param {DOM Node} node
- * @param {DOM Node} childNode
- * @return {DOM Node}
- */
- appendChild: function(node, childNode){
- return node.appendChild(childNode);
- },
-
-
- /**
- * abstracts DOM removeChild
- *
- * @param {DOM Node} childNode
- * @return {DOM Node || null}
- */
- removeChild: function(childNode){
- if (childNode.parentNode) {
- return childNode.parentNode.removeChild(childNode);
- }else{
- return null;
- }
- },
-
-
- /**
- * abstracts DOM cloneNode
- *
- * @param {DOM Node} node
- * @return {DOM Node}
- */
- clone: function(node) {
- var newNode = node.cloneNode(true);
- newNode.removeAttribute('id');
- return newNode;
- },
-
-
- /**
- * gets the text of a node
- *
- * @param {DOM Node} node
- * @return {String}
- */
- getElementText: function( node ){
- if(node && node.data){
- return node.data;
- }else{
- return '';
- }
- },
-
-
- /**
- * gets the attributes of a node - ordered by sequence in html
- *
- * @param {DOM Node} node
- * @return {Array}
- */
- getOrderedAttributes: function( node ){
- var nodeStr = node.outerHTML,
- attrs = [];
-
- for (var i = 0; i < node.attributes.length; i++) {
- var attr = node.attributes[i];
- attr.indexNum = nodeStr.indexOf(attr.name);
-
- attrs.push( attr );
- }
- return attrs.sort( modules.utils.sortObjects( 'indexNum' ) );
- },
-
-
- /**
- * decodes html entities in given text
- *
- * @param {DOM Document} doc
- * @param String} text
- * @return {String}
- */
- decodeEntities: function( doc, text ){
- //return text;
- return doc.createTextNode( text ).nodeValue;
- },
-
-
- /**
- * clones a DOM document
- *
- * @param {DOM Document} document
- * @return {DOM Document}
- */
- cloneDocument: function( document ){
- var newNode,
- newDocument = null;
-
- if( this.canCloneDocument( document )){
- newDocument = document.implementation.createHTMLDocument('');
- newNode = newDocument.importNode( document.documentElement, true );
- newDocument.replaceChild(newNode, newDocument.querySelector('html'));
- }
- return (newNode && newNode.nodeType && newNode.nodeType === 1)? newDocument : document;
- },
-
-
- /**
- * can environment clone a DOM document
- *
- * @param {DOM Document} document
- * @return {Boolean}
- */
- canCloneDocument: function( document ){
- return (document && document.importNode && document.implementation && document.implementation.createHTMLDocument);
- },
-
-
- /**
- * get the child index of a node. Used to create a node path
- *
- * @param {DOM Node} node
- * @return {Int}
- */
- getChildIndex: function (node) {
- var parent = node.parentNode,
- i = -1,
- child;
- while (parent && (child = parent.childNodes[++i])){
- if (child === node){
- return i;
- }
- }
- return -1;
- },
-
-
- /**
- * get a node's path
- *
- * @param {DOM Node} node
- * @return {Array}
- */
- getNodePath: function (node) {
- var parent = node.parentNode,
- path = [],
- index = this.getChildIndex(node);
-
- if(parent && (path = this.getNodePath(parent))){
- if(index > -1){
- path.push(index);
- }
- }
- return path;
- },
-
-
- /**
- * get a node from a path.
- *
- * @param {DOM document} document
- * @param {Array} path
- * @return {DOM Node}
- */
- getNodeByPath: function (document, path) {
- var node = document.documentElement,
- i = 0,
- index;
- while ((index = path[++i]) > -1){
- node = node.childNodes[index];
- }
- return node;
- },
-
-
- /**
- * get an array/nodeList of child nodes
- *
- * @param {DOM node} node
- * @return {Array}
- */
- getChildren: function( node ){
- return node.children;
- },
-
-
- /**
- * create a node
- *
- * @param {String} tagName
- * @return {DOM node}
- */
- createNode: function( tagName ){
- return this.document.createElement(tagName);
- },
-
-
- /**
- * create a node with text content
- *
- * @param {String} tagName
- * @param {String} text
- * @return {DOM node}
- */
- createNodeWithText: function( tagName, text ){
- var node = this.document.createElement(tagName);
- node.innerHTML = text;
- return node;
- }
-
-
-
- };
-
-
- modules.url = {
-
-
- /**
- * creates DOM objects needed to resolve URLs
- */
- init: function(){
- //this._domParser = new DOMParser();
- this._domParser = modules.domUtils.getDOMParser();
- // do not use a head tag it does not work with IE9
- this._html = ' ';
- this._nodes = this._domParser.parseFromString( this._html, 'text/html' );
- this._baseNode = modules.domUtils.getElementById(this._nodes,'base');
- this._linkNode = modules.domUtils.getElementById(this._nodes,'link');
- },
-
-
- /**
- * resolves url to absolute version using baseUrl
- *
- * @param {String} url
- * @param {String} baseUrl
- * @return {String}
- */
- resolve: function(url, baseUrl) {
- // use modern URL web API where we can
- if(modules.utils.isString(url) && modules.utils.isString(baseUrl) && url.indexOf('://') === -1){
- // this try catch is required as IE has an URL object but no constuctor support
- // http://glennjones.net/articles/the-problem-with-window-url
- try {
- var resolved = new URL(url, baseUrl).toString();
- // deal with early Webkit not throwing an error - for Safari
- if(resolved === '[object URL]'){
- resolved = URI.resolve(baseUrl, url);
- }
- return resolved;
- }catch(e){
- // otherwise fallback to DOM
- if(this._domParser === undefined){
- this.init();
- }
-
- // do not use setAttribute it does not work with IE9
- this._baseNode.href = baseUrl;
- this._linkNode.href = url;
-
- // dont use getAttribute as it returns orginal value not resolved
- return this._linkNode.href;
- }
- }else{
- if(modules.utils.isString(url)){
- return url;
- }
- return '';
- }
- },
-
- };
-
-
- /**
- * constructor
- * parses text to find just the date element of an ISO date/time string i.e. 2008-05-01
- *
- * @param {String} dateString
- * @param {String} format
- * @return {String}
- */
- modules.ISODate = function ( dateString, format ) {
- this.clear();
-
- this.format = (format)? format : 'auto'; // auto or W3C or RFC3339 or HTML5
- this.setFormatSep();
-
- // optional should be full iso date/time string
- if(arguments[0]) {
- this.parse(dateString, format);
- }
- };
-
-
- modules.ISODate.prototype = {
-
-
- /**
- * clear all states
- *
- */
- clear: function(){
- this.clearDate();
- this.clearTime();
- this.clearTimeZone();
- this.setAutoProfileState();
- },
-
-
- /**
- * clear date states
- *
- */
- clearDate: function(){
- this.dY = -1;
- this.dM = -1;
- this.dD = -1;
- this.dDDD = -1;
- },
-
-
- /**
- * clear time states
- *
- */
- clearTime: function(){
- this.tH = -1;
- this.tM = -1;
- this.tS = -1;
- this.tD = -1;
- },
-
-
- /**
- * clear timezone states
- *
- */
- clearTimeZone: function(){
- this.tzH = -1;
- this.tzM = -1;
- this.tzPN = '+';
- this.z = false;
- },
-
-
- /**
- * resets the auto profile state
- *
- */
- setAutoProfileState: function(){
- this.autoProfile = {
- sep: 'T',
- dsep: '-',
- tsep: ':',
- tzsep: ':',
- tzZulu: 'Z'
- };
- },
-
-
- /**
- * parses text to find ISO date/time string i.e. 2008-05-01T15:45:19Z
- *
- * @param {String} dateString
- * @param {String} format
- * @return {String}
- */
- parse: function( dateString, format ) {
- this.clear();
-
- var parts = [],
- tzArray = [],
- position = 0,
- datePart = '',
- timePart = '',
- timeZonePart = '';
-
- if(format){
- this.format = format;
- }
-
-
-
- // discover date time separtor for auto profile
- // Set to 'T' by default
- if(dateString.indexOf('t') > -1) {
- this.autoProfile.sep = 't';
- }
- if(dateString.indexOf('z') > -1) {
- this.autoProfile.tzZulu = 'z';
- }
- if(dateString.indexOf('Z') > -1) {
- this.autoProfile.tzZulu = 'Z';
- }
- if(dateString.toUpperCase().indexOf('T') === -1) {
- this.autoProfile.sep = ' ';
- }
-
-
- dateString = dateString.toUpperCase().replace(' ','T');
-
- // break on 'T' divider or space
- if(dateString.indexOf('T') > -1) {
- parts = dateString.split('T');
- datePart = parts[0];
- timePart = parts[1];
-
- // zulu UTC
- if(timePart.indexOf( 'Z' ) > -1) {
- this.z = true;
- }
-
- // timezone
- if(timePart.indexOf( '+' ) > -1 || timePart.indexOf( '-' ) > -1) {
- tzArray = timePart.split( 'Z' ); // incase of incorrect use of Z
- timePart = tzArray[0];
- timeZonePart = tzArray[1];
-
- // timezone
- if(timePart.indexOf( '+' ) > -1 || timePart.indexOf( '-' ) > -1) {
- position = 0;
-
- if(timePart.indexOf( '+' ) > -1) {
- position = timePart.indexOf( '+' );
- } else {
- position = timePart.indexOf( '-' );
- }
-
- timeZonePart = timePart.substring( position, timePart.length );
- timePart = timePart.substring( 0, position );
- }
- }
-
- } else {
- datePart = dateString;
- }
-
- if(datePart !== '') {
- this.parseDate( datePart );
- if(timePart !== '') {
- this.parseTime( timePart );
- if(timeZonePart !== '') {
- this.parseTimeZone( timeZonePart );
- }
- }
- }
- return this.toString( format );
- },
-
-
- /**
- * parses text to find just the date element of an ISO date/time string i.e. 2008-05-01
- *
- * @param {String} dateString
- * @param {String} format
- * @return {String}
- */
- parseDate: function( dateString, format ) {
- this.clearDate();
-
- var parts = [];
-
- // discover timezone separtor for auto profile // default is ':'
- if(dateString.indexOf('-') === -1) {
- this.autoProfile.tsep = '';
- }
-
- // YYYY-DDD
- parts = dateString.match( /(\d\d\d\d)-(\d\d\d)/ );
- if(parts) {
- if(parts[1]) {
- this.dY = parts[1];
- }
- if(parts[2]) {
- this.dDDD = parts[2];
- }
- }
-
- if(this.dDDD === -1) {
- // YYYY-MM-DD ie 2008-05-01 and YYYYMMDD ie 20080501
- parts = dateString.match( /(\d\d\d\d)?-?(\d\d)?-?(\d\d)?/ );
- if(parts[1]) {
- this.dY = parts[1];
- }
- if(parts[2]) {
- this.dM = parts[2];
- }
- if(parts[3]) {
- this.dD = parts[3];
- }
- }
- return this.toString(format);
- },
-
-
- /**
- * parses text to find just the time element of an ISO date/time string i.e. 13:30:45
- *
- * @param {String} timeString
- * @param {String} format
- * @return {String}
- */
- parseTime: function( timeString, format ) {
- this.clearTime();
- var parts = [];
-
- // discover date separtor for auto profile // default is ':'
- if(timeString.indexOf(':') === -1) {
- this.autoProfile.tsep = '';
- }
-
- // finds timezone HH:MM:SS and HHMMSS ie 13:30:45, 133045 and 13:30:45.0135
- parts = timeString.match( /(\d\d)?:?(\d\d)?:?(\d\d)?.?([0-9]+)?/ );
- if(parts[1]) {
- this.tH = parts[1];
- }
- if(parts[2]) {
- this.tM = parts[2];
- }
- if(parts[3]) {
- this.tS = parts[3];
- }
- if(parts[4]) {
- this.tD = parts[4];
- }
- return this.toTimeString(format);
- },
-
-
- /**
- * parses text to find just the time element of an ISO date/time string i.e. +08:00
- *
- * @param {String} timeString
- * @param {String} format
- * @return {String}
- */
- parseTimeZone: function( timeString, format ) {
- this.clearTimeZone();
- var parts = [];
-
- if(timeString.toLowerCase() === 'z'){
- this.z = true;
- // set case for z
- this.autoProfile.tzZulu = (timeString === 'z')? 'z' : 'Z';
- }else{
-
- // discover timezone separtor for auto profile // default is ':'
- if(timeString.indexOf(':') === -1) {
- this.autoProfile.tzsep = '';
- }
-
- // finds timezone +HH:MM and +HHMM ie +13:30 and +1330
- parts = timeString.match( /([\-\+]{1})?(\d\d)?:?(\d\d)?/ );
- if(parts[1]) {
- this.tzPN = parts[1];
- }
- if(parts[2]) {
- this.tzH = parts[2];
- }
- if(parts[3]) {
- this.tzM = parts[3];
- }
-
-
- }
- this.tzZulu = 'z';
- return this.toTimeString( format );
- },
-
-
- /**
- * returns ISO date/time string in W3C Note, RFC 3339, HTML5, or auto profile
- *
- * @param {String} format
- * @return {String}
- */
- toString: function( format ) {
- var output = '';
-
- if(format){
- this.format = format;
- }
- this.setFormatSep();
-
- if(this.dY > -1) {
- output = this.dY;
- if(this.dM > 0 && this.dM < 13) {
- output += this.dsep + this.dM;
- if(this.dD > 0 && this.dD < 32) {
- output += this.dsep + this.dD;
- if(this.tH > -1 && this.tH < 25) {
- output += this.sep + this.toTimeString( format );
- }
- }
- }
- if(this.dDDD > -1) {
- output += this.dsep + this.dDDD;
- }
- } else if(this.tH > -1) {
- output += this.toTimeString( format );
- }
-
- return output;
- },
-
-
- /**
- * returns just the time string element of an ISO date/time
- * in W3C Note, RFC 3339, HTML5, or auto profile
- *
- * @param {String} format
- * @return {String}
- */
- toTimeString: function( format ) {
- var out = '';
-
- if(format){
- this.format = format;
- }
- this.setFormatSep();
-
- // time can only be created with a full date
- if(this.tH) {
- if(this.tH > -1 && this.tH < 25) {
- out += this.tH;
- if(this.tM > -1 && this.tM < 61){
- out += this.tsep + this.tM;
- if(this.tS > -1 && this.tS < 61){
- out += this.tsep + this.tS;
- if(this.tD > -1){
- out += '.' + this.tD;
- }
- }
- }
-
-
-
- // time zone offset
- if(this.z) {
- out += this.tzZulu;
- } else {
- if(this.tzH && this.tzH > -1 && this.tzH < 25) {
- out += this.tzPN + this.tzH;
- if(this.tzM > -1 && this.tzM < 61){
- out += this.tzsep + this.tzM;
- }
- }
- }
- }
- }
- return out;
- },
-
-
- /**
- * set the current profile to W3C Note, RFC 3339, HTML5, or auto profile
- *
- */
- setFormatSep: function() {
- switch( this.format.toLowerCase() ) {
- case 'rfc3339':
- this.sep = 'T';
- this.dsep = '';
- this.tsep = '';
- this.tzsep = '';
- this.tzZulu = 'Z';
- break;
- case 'w3c':
- this.sep = 'T';
- this.dsep = '-';
- this.tsep = ':';
- this.tzsep = ':';
- this.tzZulu = 'Z';
- break;
- case 'html5':
- this.sep = ' ';
- this.dsep = '-';
- this.tsep = ':';
- this.tzsep = ':';
- this.tzZulu = 'Z';
- break;
- default:
- // auto - defined by format of input string
- this.sep = this.autoProfile.sep;
- this.dsep = this.autoProfile.dsep;
- this.tsep = this.autoProfile.tsep;
- this.tzsep = this.autoProfile.tzsep;
- this.tzZulu = this.autoProfile.tzZulu;
- }
- },
-
-
- /**
- * does current data contain a full date i.e. 2015-03-23
- *
- * @return {Boolean}
- */
- hasFullDate: function() {
- return(this.dY !== -1 && this.dM !== -1 && this.dD !== -1);
- },
-
-
- /**
- * does current data contain a minimum date which is just a year number i.e. 2015
- *
- * @return {Boolean}
- */
- hasDate: function() {
- return(this.dY !== -1);
- },
-
-
- /**
- * does current data contain a minimum time which is just a hour number i.e. 13
- *
- * @return {Boolean}
- */
- hasTime: function() {
- return(this.tH !== -1);
- },
-
- /**
- * does current data contain a minimum timezone i.e. -1 || +1 || z
- *
- * @return {Boolean}
- */
- hasTimeZone: function() {
- return(this.tzH !== -1);
- }
-
- };
-
- modules.ISODate.prototype.constructor = modules.ISODate;
-
-
- modules.dates = {
-
-
- /**
- * does text contain am
- *
- * @param {String} text
- * @return {Boolean}
- */
- hasAM: function( text ) {
- text = text.toLowerCase();
- return(text.indexOf('am') > -1 || text.indexOf('a.m.') > -1);
- },
-
-
- /**
- * does text contain pm
- *
- * @param {String} text
- * @return {Boolean}
- */
- hasPM: function( text ) {
- text = text.toLowerCase();
- return(text.indexOf('pm') > -1 || text.indexOf('p.m.') > -1);
- },
-
-
- /**
- * remove am and pm from text and return it
- *
- * @param {String} text
- * @return {String}
- */
- removeAMPM: function( text ) {
- return text.replace('pm', '').replace('p.m.', '').replace('am', '').replace('a.m.', '');
- },
-
-
- /**
- * simple test of whether ISO date string is a duration i.e. PY17M or PW12
- *
- * @param {String} text
- * @return {Boolean}
- */
- isDuration: function( text ) {
- if(modules.utils.isString( text )){
- text = text.toLowerCase();
- if(modules.utils.startWith(text, 'p') ){
- return true;
- }
- }
- return false;
- },
-
-
- /**
- * is text a time or timezone
- * i.e. HH-MM-SS or z+-HH-MM-SS 08:43 | 15:23:00:0567 | 10:34pm | 10:34 p.m. | +01:00:00 | -02:00 | z15:00 | 0843
- *
- * @param {String} text
- * @return {Boolean}
- */
- isTime: function( text ) {
- if(modules.utils.isString(text)){
- text = text.toLowerCase();
- text = modules.utils.trim( text );
- // start with timezone char
- if( text.match(':') && ( modules.utils.startWith(text, 'z') || modules.utils.startWith(text, '-') || modules.utils.startWith(text, '+') )) {
- return true;
- }
- // has ante meridiem or post meridiem
- if( text.match(/^[0-9]/) &&
- ( this.hasAM(text) || this.hasPM(text) )) {
- return true;
- }
- // contains time delimiter but not datetime delimiter
- if( text.match(':') && !text.match(/t|\s/) ) {
- return true;
- }
-
- // if it's a number of 2, 4 or 6 chars
- if(modules.utils.isNumber(text)){
- if(text.length === 2 || text.length === 4 || text.length === 6){
- return true;
- }
- }
- }
- return false;
- },
-
-
- /**
- * parses a time from text and returns 24hr time string
- * i.e. 5:34am = 05:34:00 and 1:52:04p.m. = 13:52:04
- *
- * @param {String} text
- * @return {String}
- */
- parseAmPmTime: function( text ) {
- var out = text,
- times = [];
-
- // if the string has a text : or am or pm
- if(modules.utils.isString(out)) {
- //text = text.toLowerCase();
- text = text.replace(/[ ]+/g, '');
-
- if(text.match(':') || this.hasAM(text) || this.hasPM(text)) {
-
- if(text.match(':')) {
- times = text.split(':');
- } else {
- // single number text i.e. 5pm
- times[0] = text;
- times[0] = this.removeAMPM(times[0]);
- }
-
- // change pm hours to 24hr number
- if(this.hasPM(text)) {
- if(times[0] < 12) {
- times[0] = parseInt(times[0], 10) + 12;
- }
- }
-
- // add leading zero's where needed
- if(times[0] && times[0].length === 1) {
- times[0] = '0' + times[0];
- }
-
- // rejoin text elements together
- if(times[0]) {
- text = times.join(':');
- }
- }
- }
-
- // remove am/pm strings
- return this.removeAMPM(text);
- },
-
-
- /**
- * overlays a time on a date to return the union of the two
- *
- * @param {String} date
- * @param {String} time
- * @param {String} format ( Modules.ISODate profile format )
- * @return {Object} Modules.ISODate
- */
- dateTimeUnion: function(date, time, format) {
- var isodate = new modules.ISODate(date, format),
- isotime = new modules.ISODate();
-
- isotime.parseTime(this.parseAmPmTime(time), format);
- if(isodate.hasFullDate() && isotime.hasTime()) {
- isodate.tH = isotime.tH;
- isodate.tM = isotime.tM;
- isodate.tS = isotime.tS;
- isodate.tD = isotime.tD;
- return isodate;
- } else {
- if(isodate.hasFullDate()){
- return isodate;
- }
- return new modules.ISODate();
- }
- },
-
-
- /**
- * concatenate an array of date and time text fragments to create an ISODate object
- * used for microformat value and value-title rules
- *
- * @param {Array} arr ( Array of Strings )
- * @param {String} format ( Modules.ISODate profile format )
- * @return {Object} Modules.ISODate
- */
- concatFragments: function (arr, format) {
- var out = new modules.ISODate(),
- i = 0,
- value = '';
-
- // if the fragment already contains a full date just return it once
- if(arr[0].toUpperCase().match('T')) {
- return new modules.ISODate(arr[0], format);
- }else{
- for(i = 0; i < arr.length; i++) {
- value = arr[i];
-
- // date pattern
- if( value.charAt(4) === '-' && out.hasFullDate() === false ){
- out.parseDate(value);
- }
-
- // time pattern
- if( (value.indexOf(':') > -1 || modules.utils.isNumber( this.parseAmPmTime(value) )) && out.hasTime() === false ) {
- // split time and timezone
- var items = this.splitTimeAndZone(value);
- value = items[0];
-
- // parse any use of am/pm
- value = this.parseAmPmTime(value);
- out.parseTime(value);
-
- // parse any timezone
- if(items.length > 1){
- out.parseTimeZone(items[1], format);
- }
- }
-
- // timezone pattern
- if(value.charAt(0) === '-' || value.charAt(0) === '+' || value.toUpperCase() === 'Z') {
- if( out.hasTimeZone() === false ){
- out.parseTimeZone(value);
- }
- }
-
- }
- return out;
-
- }
- },
-
-
- /**
- * parses text by splitting it into an array of time and timezone strings
- *
- * @param {String} text
- * @return {Array} Modules.ISODate
- */
- splitTimeAndZone: function ( text ){
- var out = [text],
- chars = ['-','+','z','Z'],
- i = chars.length;
-
- while (i--) {
- if(text.indexOf(chars[i]) > -1){
- out[0] = text.slice( 0, text.indexOf(chars[i]) );
- out.push( text.slice( text.indexOf(chars[i]) ) );
- break;
- }
- }
- return out;
- }
-
- };
-
-
- modules.text = {
-
- // normalised or whitespace or whitespacetrimmed
- textFormat: 'whitespacetrimmed',
-
- // block level tags, used to add line returns
- blockLevelTags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'hr', 'pre', 'table',
- 'address', 'article', 'aside', 'blockquote', 'caption', 'col', 'colgroup', 'dd', 'div',
- 'dt', 'dir', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'header', 'hgroup', 'hr',
- 'li', 'map', 'menu', 'nav', 'optgroup', 'option', 'section', 'tbody', 'testarea',
- 'tfoot', 'th', 'thead', 'tr', 'td', 'ul', 'ol', 'dl', 'details'],
-
- // tags to exclude
- excludeTags: ['noframe', 'noscript', 'template', 'script', 'style', 'frames', 'frameset'],
-
-
- /**
- * parses the text from the DOM Node
- *
- * @param {DOM Node} node
- * @param {String} textFormat
- * @return {String}
- */
- parse: function(doc, node, textFormat){
- var out;
- this.textFormat = (textFormat)? textFormat : this.textFormat;
- if(this.textFormat === 'normalised'){
- out = this.walkTreeForText( node );
- if(out !== undefined){
- return this.normalise( doc, out );
- }else{
- return '';
- }
- }else{
- return this.formatText( doc, modules.domUtils.textContent(node), this.textFormat );
- }
- },
-
-
- /**
- * parses the text from a html string
- *
- * @param {DOM Document} doc
- * @param {String} text
- * @param {String} textFormat
- * @return {String}
- */
- parseText: function( doc, text, textFormat ){
- var node = modules.domUtils.createNodeWithText( 'div', text );
- return this.parse( doc, node, textFormat );
- },
-
-
- /**
- * parses the text from a html string - only for whitespace or whitespacetrimmed formats
- *
- * @param {String} text
- * @param {String} textFormat
- * @return {String}
- */
- formatText: function( doc, text, textFormat ){
- this.textFormat = (textFormat)? textFormat : this.textFormat;
- if(text){
- var out = '',
- regex = /(<([^>]+)>)/ig;
-
- out = text.replace(regex, '');
- if(this.textFormat === 'whitespacetrimmed') {
- out = modules.utils.trimWhitespace( out );
- }
-
- //return entities.decode( out, 2 );
- return modules.domUtils.decodeEntities( doc, out );
- }else{
- return '';
- }
- },
-
-
- /**
- * normalises whitespace in given text
- *
- * @param {String} text
- * @return {String}
- */
- normalise: function( doc, text ){
- text = text.replace( / /g, ' ') ; // exchanges html entity for space into space char
- text = modules.utils.collapseWhiteSpace( text ); // removes linefeeds, tabs and addtional spaces
- text = modules.domUtils.decodeEntities( doc, text ); // decode HTML entities
- text = text.replace( '–', '-' ); // correct dash decoding
- return modules.utils.trim( text );
- },
-
-
- /**
- * walks DOM tree parsing the text from DOM Nodes
- *
- * @param {DOM Node} node
- * @return {String}
- */
- walkTreeForText: function( node ) {
- var out = '',
- j = 0;
-
- if(node.tagName && this.excludeTags.indexOf( node.tagName.toLowerCase() ) > -1){
- return out;
- }
-
- // if node is a text node get its text
- if(node.nodeType && node.nodeType === 3){
- out += modules.domUtils.getElementText( node );
- }
-
- // get the text of the child nodes
- if(node.childNodes && node.childNodes.length > 0){
- for (j = 0; j < node.childNodes.length; j++) {
- var text = this.walkTreeForText( node.childNodes[j] );
- if(text !== undefined){
- out += text;
- }
- }
- }
-
- // if it's a block level tag add an additional space at the end
- if(node.tagName && this.blockLevelTags.indexOf( node.tagName.toLowerCase() ) !== -1){
- out += ' ';
- }
-
- return (out === '')? undefined : out ;
- }
-
- };
-
-
- modules.html = {
-
- // elements which are self-closing
- selfClosingElt: ['area', 'base', 'br', 'col', 'hr', 'img', 'input', 'link', 'meta', 'param', 'command', 'keygen', 'source'],
-
-
- /**
- * parse the html string from DOM Node
- *
- * @param {DOM Node} node
- * @return {String}
- */
- parse: function( node ){
- var out = '',
- j = 0;
-
- // we do not want the outer container
- if(node.childNodes && node.childNodes.length > 0){
- for (j = 0; j < node.childNodes.length; j++) {
- var text = this.walkTreeForHtml( node.childNodes[j] );
- if(text !== undefined){
- out += text;
- }
- }
- }
-
- return out;
- },
-
-
- /**
- * walks the DOM tree parsing the html string from the nodes
- *
- * @param {DOM Document} doc
- * @param {DOM Node} node
- * @return {String}
- */
- walkTreeForHtml: function( node ) {
- var out = '',
- j = 0;
-
- // if node is a text node get its text
- if(node.nodeType && node.nodeType === 3){
- out += modules.domUtils.getElementText( node );
- }
-
-
- // exclude text which has been added with include pattern -
- if(node.nodeType && node.nodeType === 1 && modules.domUtils.hasAttribute(node, 'data-include') === false){
-
- // begin tag
- out += '<' + node.tagName.toLowerCase();
-
- // add attributes
- var attrs = modules.domUtils.getOrderedAttributes(node);
- for (j = 0; j < attrs.length; j++) {
- out += ' ' + attrs[j].name + '=' + '"' + attrs[j].value + '"';
- }
-
- if(this.selfClosingElt.indexOf(node.tagName.toLowerCase()) === -1){
- out += '>';
- }
-
- // get the text of the child nodes
- if(node.childNodes && node.childNodes.length > 0){
-
- for (j = 0; j < node.childNodes.length; j++) {
- var text = this.walkTreeForHtml( node.childNodes[j] );
- if(text !== undefined){
- out += text;
- }
- }
- }
-
- // end tag
- if(this.selfClosingElt.indexOf(node.tagName.toLowerCase()) > -1){
- out += ' />';
- }else{
- out += '' + node.tagName.toLowerCase() + '>';
- }
- }
-
- return (out === '')? undefined : out;
- }
-
-
- };
-
-
- modules.maps['h-adr'] = {
- root: 'adr',
- name: 'h-adr',
- properties: {
- 'post-office-box': {},
- 'street-address': {},
- 'extended-address': {},
- 'locality': {},
- 'region': {},
- 'postal-code': {},
- 'country-name': {}
- }
- };
-
-
- modules.maps['h-card'] = {
- root: 'vcard',
- name: 'h-card',
- properties: {
- 'fn': {
- 'map': 'p-name'
- },
- 'adr': {
- 'map': 'p-adr',
- 'uf': ['h-adr']
- },
- 'agent': {
- 'uf': ['h-card']
- },
- 'bday': {
- 'map': 'dt-bday'
- },
- 'class': {},
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'email': {
- 'map': 'u-email'
- },
- 'geo': {
- 'map': 'p-geo',
- 'uf': ['h-geo']
- },
- 'key': {
- 'map': 'u-key'
- },
- 'label': {},
- 'logo': {
- 'map': 'u-logo'
- },
- 'mailer': {},
- 'honorific-prefix': {},
- 'given-name': {},
- 'additional-name': {},
- 'family-name': {},
- 'honorific-suffix': {},
- 'nickname': {},
- 'note': {}, // could be html i.e. e-note
- 'org': {},
- 'p-organization-name': {},
- 'p-organization-unit': {},
- 'photo': {
- 'map': 'u-photo'
- },
- 'rev': {
- 'map': 'dt-rev'
- },
- 'role': {},
- 'sequence': {},
- 'sort-string': {},
- 'sound': {
- 'map': 'u-sound'
- },
- 'title': {
- 'map': 'p-job-title'
- },
- 'tel': {},
- 'tz': {},
- 'uid': {
- 'map': 'u-uid'
- },
- 'url': {
- 'map': 'u-url'
- }
- }
- };
-
-
- modules.maps['h-entry'] = {
- root: 'hentry',
- name: 'h-entry',
- properties: {
- 'entry-title': {
- 'map': 'p-name'
- },
- 'entry-summary': {
- 'map': 'p-summary'
- },
- 'entry-content': {
- 'map': 'e-content'
- },
- 'published': {
- 'map': 'dt-published'
- },
- 'updated': {
- 'map': 'dt-updated'
- },
- 'author': {
- 'uf': ['h-card']
- },
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'geo': {
- 'map': 'p-geo',
- 'uf': ['h-geo']
- },
- 'latitude': {},
- 'longitude': {},
- 'url': {
- 'map': 'u-url',
- 'relAlt': ['bookmark']
- }
- }
- };
-
-
- modules.maps['h-event'] = {
- root: 'vevent',
- name: 'h-event',
- properties: {
- 'summary': {
- 'map': 'p-name'
- },
- 'dtstart': {
- 'map': 'dt-start'
- },
- 'dtend': {
- 'map': 'dt-end'
- },
- 'description': {},
- 'url': {
- 'map': 'u-url'
- },
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'location': {
- 'uf': ['h-card']
- },
- 'geo': {
- 'uf': ['h-geo']
- },
- 'latitude': {},
- 'longitude': {},
- 'duration': {
- 'map': 'dt-duration'
- },
- 'contact': {
- 'uf': ['h-card']
- },
- 'organizer': {
- 'uf': ['h-card']},
- 'attendee': {
- 'uf': ['h-card']},
- 'uid': {
- 'map': 'u-uid'
- },
- 'attach': {
- 'map': 'u-attach'
- },
- 'status': {},
- 'rdate': {},
- 'rrule': {}
- }
- };
-
-
- modules.maps['h-feed'] = {
- root: 'hfeed',
- name: 'h-feed',
- properties: {
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'summary': {
- 'map': 'p-summary'
- },
- 'author': {
- 'uf': ['h-card']
- },
- 'url': {
- 'map': 'u-url'
- },
- 'photo': {
- 'map': 'u-photo'
- },
- }
- };
-
-
- modules.maps['h-geo'] = {
- root: 'geo',
- name: 'h-geo',
- properties: {
- 'latitude': {},
- 'longitude': {}
- }
- };
-
-
- modules.maps['h-item'] = {
- root: 'item',
- name: 'h-item',
- subTree: false,
- properties: {
- 'fn': {
- 'map': 'p-name'
- },
- 'url': {
- 'map': 'u-url'
- },
- 'photo': {
- 'map': 'u-photo'
- }
- }
- };
-
-
- modules.maps['h-listing'] = {
- root: 'hlisting',
- name: 'h-listing',
- properties: {
- 'version': {},
- 'lister': {
- 'uf': ['h-card']
- },
- 'dtlisted': {
- 'map': 'dt-listed'
- },
- 'dtexpired': {
- 'map': 'dt-expired'
- },
- 'location': {},
- 'price': {},
- 'item': {
- 'uf': ['h-card','a-adr','h-geo']
- },
- 'summary': {
- 'map': 'p-name'
- },
- 'description': {
- 'map': 'e-description'
- },
- 'listing': {}
- }
- };
-
-
- modules.maps['h-news'] = {
- root: 'hnews',
- name: 'h-news',
- properties: {
- 'entry': {
- 'uf': ['h-entry']
- },
- 'geo': {
- 'uf': ['h-geo']
- },
- 'latitude': {},
- 'longitude': {},
- 'source-org': {
- 'uf': ['h-card']
- },
- 'dateline': {
- 'uf': ['h-card']
- },
- 'item-license': {
- 'map': 'u-item-license'
- },
- 'principles': {
- 'map': 'u-principles',
- 'relAlt': ['principles']
- }
- }
- };
-
-
- modules.maps['h-org'] = {
- root: 'h-x-org', // drop this from v1 as it causes issue with fn org hcard pattern
- name: 'h-org',
- childStructure: true,
- properties: {
- 'organization-name': {},
- 'organization-unit': {}
- }
- };
-
-
- modules.maps['h-product'] = {
- root: 'hproduct',
- name: 'h-product',
- properties: {
- 'brand': {
- 'uf': ['h-card']
- },
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'price': {},
- 'description': {
- 'map': 'e-description'
- },
- 'fn': {
- 'map': 'p-name'
- },
- 'photo': {
- 'map': 'u-photo'
- },
- 'url': {
- 'map': 'u-url'
- },
- 'review': {
- 'uf': ['h-review', 'h-review-aggregate']
- },
- 'listing': {
- 'uf': ['h-listing']
- },
- 'identifier': {
- 'map': 'u-identifier'
- }
- }
- };
-
-
- modules.maps['h-recipe'] = {
- root: 'hrecipe',
- name: 'h-recipe',
- properties: {
- 'fn': {
- 'map': 'p-name'
- },
- 'ingredient': {
- 'map': 'e-ingredient'
- },
- 'yield': {},
- 'instructions': {
- 'map': 'e-instructions'
- },
- 'duration': {
- 'map': 'dt-duration'
- },
- 'photo': {
- 'map': 'u-photo'
- },
- 'summary': {},
- 'author': {
- 'uf': ['h-card']
- },
- 'published': {
- 'map': 'dt-published'
- },
- 'nutrition': {},
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- }
- };
-
-
- modules.maps['h-resume'] = {
- root: 'hresume',
- name: 'h-resume',
- properties: {
- 'summary': {},
- 'contact': {
- 'uf': ['h-card']
- },
- 'education': {
- 'uf': ['h-card', 'h-event']
- },
- 'experience': {
- 'uf': ['h-card', 'h-event']
- },
- 'skill': {},
- 'affiliation': {
- 'uf': ['h-card']
- }
- }
- };
-
-
- modules.maps['h-review-aggregate'] = {
- root: 'hreview-aggregate',
- name: 'h-review-aggregate',
- properties: {
- 'summary': {
- 'map': 'p-name'
- },
- 'item': {
- 'map': 'p-item',
- 'uf': ['h-item', 'h-geo', 'h-adr', 'h-card', 'h-event', 'h-product']
- },
- 'rating': {},
- 'average': {},
- 'best': {},
- 'worst': {},
- 'count': {},
- 'votes': {},
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'url': {
- 'map': 'u-url',
- 'relAlt': ['self', 'bookmark']
- }
- }
- };
-
-
- modules.maps['h-review'] = {
- root: 'hreview',
- name: 'h-review',
- properties: {
- 'summary': {
- 'map': 'p-name'
- },
- 'description': {
- 'map': 'e-description'
- },
- 'item': {
- 'map': 'p-item',
- 'uf': ['h-item', 'h-geo', 'h-adr', 'h-card', 'h-event', 'h-product']
- },
- 'reviewer': {
- 'uf': ['h-card']
- },
- 'dtreviewer': {
- 'map': 'dt-reviewer'
- },
- 'rating': {},
- 'best': {},
- 'worst': {},
- 'category': {
- 'map': 'p-category',
- 'relAlt': ['tag']
- },
- 'url': {
- 'map': 'u-url',
- 'relAlt': ['self', 'bookmark']
- }
- }
- };
-
-
- modules.rels = {
- // xfn
- 'friend': [ 'yes','external'],
- 'acquaintance': [ 'yes','external'],
- 'contact': [ 'yes','external'],
- 'met': [ 'yes','external'],
- 'co-worker': [ 'yes','external'],
- 'colleague': [ 'yes','external'],
- 'co-resident': [ 'yes','external'],
- 'neighbor': [ 'yes','external'],
- 'child': [ 'yes','external'],
- 'parent': [ 'yes','external'],
- 'sibling': [ 'yes','external'],
- 'spouse': [ 'yes','external'],
- 'kin': [ 'yes','external'],
- 'muse': [ 'yes','external'],
- 'crush': [ 'yes','external'],
- 'date': [ 'yes','external'],
- 'sweetheart': [ 'yes','external'],
- 'me': [ 'yes','external'],
-
- // other rel=*
- 'license': [ 'yes','yes'],
- 'nofollow': [ 'no','external'],
- 'tag': [ 'no','yes'],
- 'self': [ 'no','external'],
- 'bookmark': [ 'no','external'],
- 'author': [ 'no','external'],
- 'home': [ 'no','external'],
- 'directory': [ 'no','external'],
- 'enclosure': [ 'no','external'],
- 'pronunciation': [ 'no','external'],
- 'payment': [ 'no','external'],
- 'principles': [ 'no','external']
-
- };
-
-
-
- var External = {
- version: modules.version,
- livingStandard: modules.livingStandard
- };
-
-
- External.get = function(options){
- var parser = new modules.Parser();
- addV1(parser, options);
- return parser.get( options );
- };
-
-
- External.getParent = function(node, options){
- var parser = new modules.Parser();
- addV1(parser, options);
- return parser.getParent( node, options );
- };
-
-
- External.count = function(options){
- var parser = new modules.Parser();
- addV1(parser, options);
- return parser.count( options );
- };
-
-
- External.isMicroformat = function( node, options ){
- var parser = new modules.Parser();
- addV1(parser, options);
- return parser.isMicroformat( node, options );
- };
-
-
- External.hasMicroformats = function( node, options ){
- var parser = new modules.Parser();
- addV1(parser, options);
- return parser.hasMicroformats( node, options );
- };
-
-
- function addV1(parser, options){
- if(options && options.maps){
- if(Array.isArray(options.maps)){
- parser.add(options.maps);
- }else{
- parser.add([options.maps]);
- }
- }
- }
-
-
- return External;
-
-
-}));
-try {
- // mozilla jsm support
- Components.utils.importGlobalProperties(["URL"]);
-} catch(e) {}
-this.EXPORTED_SYMBOLS = ['Microformats'];
diff --git a/toolkit/components/microformats/moz.build b/toolkit/components/microformats/moz.build
index 3e2487bb3b54..ce29a105e45d 100644
--- a/toolkit/components/microformats/moz.build
+++ b/toolkit/components/microformats/moz.build
@@ -4,8 +4,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
+
EXTRA_JS_MODULES += [
- 'microformat-shiv.js',
'Microformats.js',
]
diff --git a/toolkit/components/microformats/test/interface-tests/count-test.js b/toolkit/components/microformats/test/interface-tests/count-test.js
deleted file mode 100644
index 864d7f707cf8..000000000000
--- a/toolkit/components/microformats/test/interface-tests/count-test.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Unit test for count
-*/
-
-assert = chai.assert;
-
-
-describe('Microformat.count', function() {
-
- it('count', function(){
-
- var doc,
- node,
- result;
-
- var html = 'Glenn Jane Event 2015-07-01 ';
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- };
-
- result = Microformats.count(options);
- assert.deepEqual( result, {'h-event': 1,'h-card': 2} );
-
- });
-
-
- it('count rels', function(){
-
- var doc,
- node,
- result;
-
- var html = 'Glenn Jane Event 2015-07-01 ';
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- };
-
- result = Microformats.count(options);
- assert.deepEqual( result, {'h-event': 1,'h-card': 2, 'rels': 1} );
-
- });
-
-
- it('count - no results', function(){
-
- var doc,
- node,
- result;
-
- var html = 'Jane ';
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- };
-
- result = Microformats.count(options);
- assert.deepEqual( result, {} );
-
- });
-
-
-
- it('count - no options', function(){
-
- var result;
-
- result = Microformats.count({});
- assert.deepEqual( result, {} );
-
- });
-
-
- it('count - options.html', function(){
-
- var options = {},
- result;
-
- options.html = 'Glenn Jane Event 2015-07-01 ';
-
- result = Microformats.count(options);
- assert.deepEqual( result, {'h-event': 1,'h-card': 2} );
-
- });
-
-
-
- });
\ No newline at end of file
diff --git a/toolkit/components/microformats/test/interface-tests/experimental-test.js b/toolkit/components/microformats/test/interface-tests/experimental-test.js
deleted file mode 100644
index 0bd43a20baaf..000000000000
--- a/toolkit/components/microformats/test/interface-tests/experimental-test.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Unit test for get
-*/
-
-assert = chai.assert;
-
-
-describe('experimental', function() {
-
- it('h-geo - geo data writen as lat;lon', function(){
-
- var expected = {
- 'items': [{
- 'type': ['h-geo'],
- 'properties': {
- 'name': ['30.267991;-97.739568'],
- 'latitude': [30.267991],
- 'longitude': [-97.739568]
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- },
- options = {
- 'html': '30.267991;-97.739568
',
- 'baseUrl': 'http://example.com',
- 'dateFormat': 'html5',
- 'parseLatLonGeo': true
- };
-
- var result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
-});
\ No newline at end of file
diff --git a/toolkit/components/microformats/test/interface-tests/get-test.js b/toolkit/components/microformats/test/interface-tests/get-test.js
deleted file mode 100644
index caaba5e7a6d7..000000000000
--- a/toolkit/components/microformats/test/interface-tests/get-test.js
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
-Unit test for get
-*/
-
-assert = chai.assert;
-
-
-describe('Microformat.get', function() {
-
-
- var expected = {
- 'items': [{
- 'type': ['h-card'],
- 'properties': {
- 'name': ['Glenn Jones'],
- 'url': ['http://glennjones.net']
- }
- }],
- 'rels': {
- 'bookmark': ['http://glennjones.net'],
- 'alternate': ['http://example.com/fr'],
- 'home': ['http://example.com/fr']
- },
- 'rel-urls': {
- 'http://glennjones.net': {
- 'text': 'Glenn Jones',
- 'rels': ['bookmark']
- },
- 'http://example.com/fr': {
- 'media': 'handheld',
- 'hreflang': 'fr',
- 'text': 'French mobile homepage',
- 'rels': ['alternate', 'home']
- }
- }
- },
- html = 'French mobile homepage ';
-
-
-
-
-
- it('get - no options.node parse this document', function(){
- var result;
-
- result = Microformats.get({});
- assert.deepEqual( result.items, [] );
- });
-
-
- it('get - standard', function(){
-
- var doc,
- node,
- options,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'baseUrl': 'http://example.com',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
- it('get - doc pass to node', function(){
-
- var doc,
- node,
- options,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html;
- doc.body.appendChild(node);
-
- options ={
- 'node': doc,
- 'baseUrl': 'http://example.com',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
- it('get - pass base tag', function(){
-
- var doc,
- node,
- options,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html + ' ';
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
- it('get - pass no document', function(){
-
- var doc,
- node,
- options,
- parser,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = html + ' ';
- doc.body.appendChild(node);
-
- options ={
- 'node': doc,
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
- it('get - textFormat: normalised', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = '\n';
- altHTML += ' Glenn \n';
- altHTML += ' Jones \n';
- altHTML += ' \n';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'textFormat': 'normalised',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.name[0], 'Glenn Jones' );
-
- });
-
-
- it('get - textFormat: whitespace', function(){
-
- var doc,
- node,
- options,
- parser,
- result;
-
- var altHTML = '\n';
- altHTML += ' Glenn \n';
- altHTML += ' Jones \n';
- altHTML += ' \n';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'textFormat': 'whitespace',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.name[0], '\n Glenn\n Jones\n' );
-
- });
-
-
-
- it('get - textFormat: whitespacetrimmed', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = '\n';
- altHTML += ' Glenn \n';
- altHTML += ' Jones \n';
- altHTML += ' \n';
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'textFormat': 'whitespacetrimmed',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.name[0], 'Glenn\n Jones' );
-
- });
-
-
- it('get - dateFormat: auto', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'dateFormat': 'auto'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.start[0], '2015-07-01t17:30z' );
-
- });
-
-
- it('get - dateFormat: w3c', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'dateFormat': 'w3c'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.start[0], '2015-07-01T17:30Z' );
-
- });
-
-
- it('get - dateFormat: html5', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.start[0], '2015-07-01 17:30Z' );
-
- });
-
-
-
- it('get - dateFormat: rfc3339', function(){
-
- var doc,
- node,
- options,
-
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'dateFormat': 'rfc3339'
- };
-
- result = Microformats.get(options);
- assert.equal( result.items[0].properties.start[0], '20150701T1730Z' );
-
- });
-
-
-
- it('get - filters h-card', function(){
-
- var doc,
- node,
- options,
- parser,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
Glenn Jones ';
- var altExpected = {
- 'items': [{
- 'type': ['h-card'],
- 'properties': {
- 'name': ['Glenn Jones'],
- 'url': ['http://glennjones.net']
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- }
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'filters': ['h-card'],
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - filters h-event', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
Glenn Jones ';
- var altExpected = {
- 'items': [{
- 'type': ['h-event'],
- 'properties': {
- 'name': ['Pub'],
- 'start': ['2015-07-01 17:30Z']
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- }
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'filters': ['h-event'],
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - filters h-card and h-event', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
Glenn Jones ';
- var altExpected = {
- 'items': [{
- 'type': ['h-event'],
- 'properties': {
- 'name': ['Pub'],
- 'start': ['2015-07-01 17:30Z']
- }
- },
- {
- 'type': ['h-card'],
- 'properties': {
- 'name': ['Glenn Jones'],
- 'url': ['http://glennjones.net']
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- }
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'filter': ['h-event'],
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - filters h-card no result', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = 'Pub 2015-07-01t17:30z
';
- var altExpected = {
- 'items': [],
- 'rels': {},
- 'rel-urls': {}
- }
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'filters': ['h-card'],
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - filters h-card match v1 format', function(){
-
- var doc,
- node,
- options,
- parser,
- result;
-
- var altHTML = 'Glenn Jones ';
- var altExpected = {
- 'items': [{
- 'type': ['h-card'],
- 'properties': {
- 'name': ['Glenn Jones']
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- }
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'filter': ['h-card'],
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - add new v1 format through options', function(){
-
- var doc,
- node,
- options,
- result;
-
- var altHTML = '£36.78
';
- var altExpected = {
- 'items': [{
- 'type': ['h-payment'],
- 'properties': {
- 'amount': ['36.78']
- }
- }],
- 'rels': {},
- 'rel-urls': {}
- };
- var v1Definition = {
- root: 'hpayment',
- name: 'h-payment',
- properties: {
- 'amount': {}
- }
- };
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
-
- options ={
- 'node': node,
- 'maps': v1Definition,
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('get - options.html', function(){
-
- var options,
- result;
-
- options ={
- 'html': html,
- 'baseUrl': 'http://example.com',
- 'dateFormat': 'html5'
- };
-
- result = Microformats.get(options);
- assert.deepEqual( result, expected );
-
- });
-
-
-
-
-
-});
\ No newline at end of file
diff --git a/toolkit/components/microformats/test/interface-tests/getParent-test.js b/toolkit/components/microformats/test/interface-tests/getParent-test.js
deleted file mode 100644
index 0da8af442027..000000000000
--- a/toolkit/components/microformats/test/interface-tests/getParent-test.js
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
-Unit test for getParent
-*/
-
-assert = chai.assert;
-
-
-describe('Microformat.getParent', function() {
-
- var HTML = 'Pub 2015-07-01t17:30z
';
- var emptyExpected = {
- "items": [],
- "rels": {},
- "rel-urls": {}
- };
- var expected = {
- "items": [
- {
- "type": [
- "h-event"
- ],
- "properties": {
- "name": [
- "Pub"
- ],
- "start": [
- "2015-07-01 17:30Z"
- ]
- }
- }
- ],
- "rels": {},
- "rel-urls": {}
- };
- var options = {'dateFormat': 'html5'};
-
-
-
-
- it('getParent with parent', function(){
-
- var doc,
- node,
- span,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = HTML;
- doc.body.appendChild(node);
- span = doc.querySelector('.dt-start');
-
- result = Microformats.getParent(span,options);
- assert.deepEqual( result, expected );
-
- });
-
-
-
- it('getParent without parent', function(){
-
- var doc,
- node,
- parser,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = HTML;
- doc.body.appendChild(node);
-
- result = Microformats.getParent(node,options);
- assert.deepEqual( result, emptyExpected );
-
- });
-
-
- it('getParent found with option.filters', function(){
-
- var doc,
- node,
- span,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = HTML;
- doc.body.appendChild(node);
- span = doc.querySelector('.dt-start');
-
- result = Microformats.getParent( span, {'filters': ['h-event'], 'dateFormat': 'html5'} );
- assert.deepEqual( result, expected );
-
- });
-
-
- it('getParent not found with option.filters', function(){
-
- var doc,
- node,
- span,
- result;
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = HTML;
- doc.body.appendChild(node);
- span = doc.querySelector('.dt-start');
-
- result = Microformats.getParent( span, {'filters': ['h-card'], 'dateFormat': 'html5'} );
- assert.deepEqual( result, emptyExpected );
-
- });
-
-
- it('getParent use option.filters to up through h-*', function(){
-
- var doc,
- node,
- span,
- result;
-
- var altHTML = 'test this
Glenn Jones 2015-07-01t17:30z ';
- var altExpected = {
- "items": [
- {
- "type": [
- "h-entry"
- ],
- "properties": {
- "name": [
- "test"
- ],
- "content": [
- {
- "value": "this",
- "html": "this"
- }
- ],
- "author": [
- {
- "value": "Glenn Jones",
- "type": [
- "h-card"
- ],
- "properties": {
- "name": [
- "Glenn Jones"
- ],
- "url": [
- "http://glennjones.net"
- ]
- }
- }
- ],
- "publish": [
- "2015-07-01 17:30Z"
- ]
- }
- }
- ],
- "rels": {},
- "rel-urls": {}
- };
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
- span = doc.querySelector('.h-card .p-name');
-
- result = Microformats.getParent( span, {'filters': ['h-entry'], 'dateFormat': 'html5'} );
- assert.deepEqual( result, altExpected );
-
- });
-
-
- it('getParent stop at first h-* parent', function(){
-
- var doc,
- node,
- span,
- result;
-
- var altHTML = 'test this
Glenn Jones 2015-07-01t17:30z ';
- var altExpected = {
- "items": [
- {
- "type": [
- "h-card"
- ],
- "properties": {
- "name": [
- "Glenn Jones"
- ],
- "url": [
- "http://glennjones.net"
- ]
- }
- }
- ],
- "rels": {},
- "rel-urls": {}
- };
-
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- node.innerHTML = altHTML;
- doc.body.appendChild(node);
- span = doc.querySelector('.h-card .p-name');
-
- result = Microformats.getParent( span, options );
- assert.deepEqual( result, altExpected );
-
- });
-
-
-});
\ No newline at end of file
diff --git a/toolkit/components/microformats/test/interface-tests/hasMicroformats-test.js b/toolkit/components/microformats/test/interface-tests/hasMicroformats-test.js
deleted file mode 100644
index e08327b92ad3..000000000000
--- a/toolkit/components/microformats/test/interface-tests/hasMicroformats-test.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
-Unit test for hasMicroformat
-*/
-
-assert = chai.assert;
-
-
-describe('Microformat.hasMicroformats', function() {
-
- it('true - v2 on node', function(){
-
- var doc,
- node;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'a' );
-
- assert.isTrue( Microformats.hasMicroformats( node ) );
-
- });
-
-
- it('true - v1 on node', function(){
-
- var doc,
- node;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'a' );
-
- assert.isTrue( Microformats.hasMicroformats( node ) );
-
- });
-
-
- it('true - v2 filter on node', function(){
-
- var doc,
- node;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'a' );
-
- assert.isTrue( Microformats.hasMicroformats( node, {'filters': ['h-card']} ) );
-
- });
-
-
- it('true - v1 filter on node', function(){
-
- var doc,
- node;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'a' );
-
- assert.isTrue( Microformats.hasMicroformats( node, {'filters': ['h-card']} ) );
-
- });
-
-
- it('false - v2 filter on node', function(){
-
- var doc,
- node;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'a' );
-
- assert.isFalse( Microformats.hasMicroformats( node, {'filters': ['h-entry']} ) );
-
- });
-
-
-
- it('false - property', function(){
-
- var doc,
- node,
- parser;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'span' );
-
- assert.isFalse( Microformats.hasMicroformats( node ) );
-
- });
-
-
- it('false - no class', function(){
-
- var doc,
- node,
- parser;
-
- var html = 'Glenn ';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
- node = doc.querySelector( 'span' );
-
- assert.isFalse( Microformats.hasMicroformats( node ) );
-
- });
-
-
- it('false - no node', function(){
- assert.isFalse( Microformats.hasMicroformats( ) );
- });
-
-
- it('false - undefined node', function(){
- assert.isFalse( Microformats.hasMicroformats( undefined ) );
- });
-
-
- it('true - child', function(){
-
- var doc,
- node;
-
- var html = '';
-
- doc = document.implementation.createHTMLDocument('New Document');
- node = document.createElement('div');
- doc.body.appendChild( node );
- node.innerHTML = html;
-
- assert.isTrue( Microformats.hasMicroformats( node ) );
-
- });
-
-
-
- it('true - document', function(){
-
- var doc,
- node;
-
- var html = '';
-
- var dom = new DOMParser();
- doc = dom.parseFromString( html, 'text/html' );
-
- assert.isTrue( Microformats.hasMicroformats( doc ) );
-
- });
-
-
-
-
-
- });
\ No newline at end of file
diff --git a/toolkit/components/microformats/test/interface-tests/index.html b/toolkit/components/microformats/test/interface-tests/index.html
deleted file mode 100644
index 19b499ae1eb5..000000000000
--- a/toolkit/components/microformats/test/interface-tests/index.html
+++ /dev/null
@@ -1,68 +0,0 @@
-Mocha
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Microformats-shiv: interface tests
-
-
-
-