1 /* 2 * jQuery CURIE @VERSION 3 * 4 * Copyright (c) 2008,2009 Jeni Tennison 5 * Licensed under the MIT (MIT-LICENSE.txt) 6 * 7 * Depends: 8 * jquery.uri.js 9 */ 10 /** 11 * @fileOverview XML Namespace processing 12 * @author <a href="mailto:jeni@jenitennison.com">Jeni Tennison</a> 13 * @copyright (c) 2008,2009 Jeni Tennison 14 * @license MIT license (MIT-LICENSE.txt) 15 * @version 1.0 16 * @requires jquery.uri.js 17 */ 18 19 /*global jQuery */ 20 (function ($) { 21 22 var 23 xmlnsRegex = /\sxmlns(?::([^ =]+))?\s*=\s*(?:"([^"]*)"|'([^']*)')/g; 24 25 /** 26 * Returns the namespaces declared in the scope of the first selected element, or 27 * adds a namespace declaration to all selected elements. Pass in no parameters 28 * to return all namespaces bindings on the first selected element. If only 29 * the prefix parameter is specified, this method will return the namespace 30 * URI that is bound to the specified prefix on the first element in the selection 31 * If the prefix and uri parameters are both specified, this method will 32 * add the binding of the specified prefix and namespace URI to all elements 33 * in the selection. 34 * @methodOf jQuery# 35 * @name jQuery#xmlns 36 * @param {String} [prefix] Restricts the namespaces returned to only the namespace with the specified namespace prefix. 37 * @param {String|jQuery.uri} [uri] Adds a namespace declaration to the selected elements that maps the specified prefix to the specified namespace. 38 * @param {Object} [inherited] A map of inherited namespace bindings. 39 * @returns {Object|jQuery.uri|jQuery} 40 * @example 41 * // Retrieve all of the namespace bindings on the HTML document element 42 * var nsMap = $('html').xmlns(); 43 * @example 44 * // Retrieve the namespace URI mapped to the 'dc' prefix on the HTML document element 45 * var dcNamespace = $('html').xmlns('dc'); 46 * @example 47 * // Create a namespace declaration that binds the 'dc' prefix to the URI 'http://purl.org/dc/elements/1.1/' 48 * $('html').xmlns('dc', 'http://purl.org/dc/elements/1.1/'); 49 */ 50 $.fn.xmlns = function (prefix, uri, inherited) { 51 var 52 elem = this.eq(0), 53 ns = elem.data('xmlns'), 54 e = elem[0], a, p, i, 55 decl = prefix ? 'xmlns:' + prefix : 'xmlns', 56 value, 57 tag, found = false; 58 if (uri === undefined) { 59 if (prefix === undefined) { // get the in-scope declarations on the first element 60 if (ns === undefined) { 61 ns = {}; 62 if (e.attributes && e.attributes.getNamedItemNS) { 63 for (i = 0; i < e.attributes.length; i += 1) { 64 a = e.attributes[i]; 65 if (/^xmlns(:(.+))?$/.test(a.nodeName)) { 66 prefix = /^xmlns(:(.+))?$/.exec(a.nodeName)[2] || ''; 67 value = a.nodeValue; 68 if (prefix === '' || value !== '') { 69 ns[prefix] = $.uri(a.nodeValue); 70 found = true; 71 } 72 } 73 } 74 } else { 75 tag = /<[^>]+>/.exec(e.outerHTML); 76 a = xmlnsRegex.exec(tag); 77 while (a !== null) { 78 prefix = a[1] || ''; 79 value = a[2] || a[3]; 80 if (prefix === '' || value !== '') { 81 ns[prefix] = $.uri(a[2] || a[3]); 82 found = true; 83 } 84 a = xmlnsRegex.exec(tag); 85 } 86 xmlnsRegex.lastIndex = 0; 87 } 88 inherited = inherited || (e.parentNode.nodeType === 1 ? elem.parent().xmlns() : {}); 89 ns = found ? $.extend({}, inherited, ns) : inherited; 90 elem.data('xmlns', ns); 91 } 92 return ns; 93 } else if (typeof prefix === 'object') { // set the prefix mappings defined in the object 94 for (p in prefix) { 95 if (typeof prefix[p] === 'string') { 96 this.xmlns(p, prefix[p]); 97 } 98 } 99 this.find('*').andSelf().removeData('xmlns'); 100 return this; 101 } else { // get the in-scope declaration associated with this prefix on the first element 102 if (ns === undefined) { 103 ns = elem.xmlns(); 104 } 105 return ns[prefix]; 106 } 107 } else { // set 108 this.find('*').andSelf().removeData('xmlns'); 109 return this.attr(decl, uri); 110 } 111 }; 112 113 /** 114 * Removes one or more XML namespace bindings from the selected elements. 115 * @methodOf jQuery# 116 * @name jQuery#removeXmlns 117 * @param {String|Object|String[]} prefix The prefix(es) of the XML namespace bindings that are to be removed from the selected elements. 118 * @returns {jQuery} The original jQuery object. 119 * @example 120 * // Remove the foaf namespace declaration from the body element: 121 * $('body').removeXmlns('foaf'); 122 * @example 123 * // Remove the foo and bar namespace declarations from all h2 elements 124 * $('h2').removeXmlns(['foo', 'bar']); 125 * @example 126 * // Remove the foo and bar namespace declarations from all h2 elements 127 * var namespaces = { foo : 'http://www.example.org/foo', bar : 'http://www.example.org/bar' }; 128 * $('h2').removeXmlns(namespaces); 129 */ 130 $.fn.removeXmlns = function (prefix) { 131 var decl, p, i; 132 if (typeof prefix === 'object') { 133 if (prefix.length === undefined) { // assume an object representing namespaces 134 for (p in prefix) { 135 if (typeof prefix[p] === 'string') { 136 this.removeXmlns(p); 137 } 138 } 139 } else { // it's an array 140 for (i = 0; i < prefix.length; i += 1) { 141 this.removeXmlns(prefix[i]); 142 } 143 } 144 } else { 145 decl = prefix ? 'xmlns:' + prefix : 'xmlns'; 146 this.removeAttr(decl); 147 } 148 this.find('*').andSelf().removeData('xmlns'); 149 return this; 150 }; 151 152 $.fn.qname = function (name) { 153 var m, prefix, namespace; 154 if (name === undefined) { 155 if (this[0].outerHTML === undefined) { 156 name = this[0].nodeName.toLowerCase(); 157 } else { 158 name = /<([^ >]+)/.exec(this[0].outerHTML)[1].toLowerCase(); 159 } 160 } 161 if (name === '?xml:namespace') { 162 // there's a prefix on the name, but we can't get at it 163 throw "XMLinHTML: Unable to get the prefix to resolve the name of this element"; 164 } 165 m = /^(([^:]+):)?([^:]+)$/.exec(name); 166 prefix = m[2] || ''; 167 namespace = this.xmlns(prefix); 168 if (namespace === undefined && prefix !== '') { 169 throw "MalformedQName: The prefix " + prefix + " is not declared"; 170 } 171 return { 172 namespace: namespace, 173 localPart: m[3], 174 prefix: prefix, 175 name: name 176 }; 177 }; 178 179 })(jQuery); 180