X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/8132fc186eb0c5fd02c86828c3a4735754296d02..5913c54d19b8f6775633176032161d49f9b2f1aa:/src/redakcja/static/js/lib/jquery/jquery.xmlns.js diff --git a/src/redakcja/static/js/lib/jquery/jquery.xmlns.js b/src/redakcja/static/js/lib/jquery/jquery.xmlns.js new file mode 100644 index 00000000..96c5a559 --- /dev/null +++ b/src/redakcja/static/js/lib/jquery/jquery.xmlns.js @@ -0,0 +1,411 @@ +// +// jquery.xmlns.js: xml-namespace selector support for jQuery +// +// This plugin modifies the jQuery tag and attribute selectors to +// support optional namespace specifiers as defined in CSS 3: +// +// $("elem") - matches 'elem' nodes in the default namespace +// $("|elem") - matches 'elem' nodes that don't have a namespace +// $("NS|elem") - matches 'elem' nodes in declared namespace 'NS' +// $("*|elem") - matches 'elem' nodes in any namespace +// $("NS|*") - matches any nodes in declared namespace 'NS' +// +// A similar synax is also supported for attribute selectors, but note +// that the default namespace does *not* apply to attributes - a missing +// or empty namespace selector selects only attributes with no namespace. +// +// In a slight break from the W3C standards, and with a nod to ease of +// implementation, the empty namespace URI is treated as equivalent to +// an unspecified namespace. Plenty of browsers seem to make the same +// assumption... +// +// Namespace declarations live in the $.xmlns object, which is a simple +// mapping from namespace ids to namespace URIs. The default namespace +// is determined by the value associated with the empty string. +// +// $.xmlns.D = "DAV:" +// $.xmlns.FOO = "http://www.foo.com/xmlns/foobar" +// $.xmlns[""] = "http://www.example.com/new/default/namespace/" +// +// Unfortunately this is a global setting - I can't find a way to do +// query-object-specific namespaces since the jQuery selector machinery +// is stateless. However, you can use the 'xmlns' function to push and +// pop namespace delcarations with ease: +// +// $().xmlns({D:"DAV:"}) // pushes the DAV: namespace +// $().xmlns("DAV:") // makes DAV: the default namespace +// $().xmlns(false) // pops the namespace we just pushed +// $().xmlns(false) // pops again, returning to defaults +// +// To execute this as a kind of "transaction", pass a function as the +// second argument. It will be executed in the context of the current +// jQuery object: +// +// $().xmlns("DAV:",function() { +// // The default namespace is DAV: within this function, +// // but it is reset to the previous value on exit. +// return this.find("response").each(...); +// }).find("div") +// +// If you pass a string as a function, it will be executed against the +// current jQuery object using find(); i.e. the following will find all +// "href" elements in the "DAV:" namespace: +// +// $().xmlns("DAV:","href") +// +// +// And finally, the legal stuff: +// +// Copyright (c) 2009, Ryan Kelly. +// TAG and ATTR functions derived from jQuery's selector.js. +// Dual licensed under the MIT and GPL licenses. +// http://docs.jquery.com/License +// + +(function($) { + +// Some common default namespaces, that are treated specially by browsers. +// +var default_xmlns = { + "xml": "http://www.w3.org/XML/1998/namespace", + "xmlns": "http://www.w3.org/2000/xmlns/", + "html": "http://www.w3.org/1999/xhtml/" +}; + + +// A reverse mapping for common namespace prefixes. +// +var default_xmlns_rev = {} +for(var k in default_xmlns) { + default_xmlns_rev[default_xmlns[k]] = k; +} + + +// $.xmlns is a mapping from namespace identifiers to namespace URIs. +// The default default-namespace is "*", and we provide some additional +// defaults that are specified in the XML Namespaces standard. +// +$.extend({xmlns: $.extend({},default_xmlns,{"":"*"})}); + + +// jQuery method to push/pop namespace declarations. +// +// If a single argument is specified: +// * if it's a mapping, push those namespaces onto the stack +// * if it's a string, push that as the default namespace +// * if it evaluates to false, pop the latest namespace +// +// If two arguments are specified, the second is executed "transactionally" +// using the namespace declarations found in the first. It can be either a +// a selector string (in which case it is passed to this.find()) or a function +// (in which case it is called in the context of the current jQuery object). +// The given namespace mapping is automatically pushed before executing and +// popped afterwards. +// +var xmlns_stack = []; +$.fn.extend({xmlns: function(nsmap,func) { + if(typeof nsmap == "string") { + nsmap = {"":nsmap}; + } + if(nsmap) { + xmlns_stack.push($.xmlns); + $.xmlns = $.extend({},$.xmlns,nsmap); + if(func !== undefined) { + if(typeof func == "string") { + return this.find(func).xmlns(undefined) + } else { + var self = this; + try { + self = func.call(this); + if(!self) { + self = this; + } + } finally { + self.xmlns(undefined); + } + return self + } + } else { + return this; + } + } else { + $.xmlns = (xmlns_stack ? xmlns_stack.pop() : {}); + return this; + } +}}); + + +// Convert a namespace prefix into a namespace URI, based +// on the delcarations made in $.xmlns. +// +var getNamespaceURI = function(id) { + // No namespace id, use the default. + if(!id) { + return $.xmlns[""]; + } + // Strip the pipe character from the specifier + id = id.substr(0,id.length-1); + // Certain special namespaces aren't mapped to a URI + if(id == "" || id == "*") { + return id; + } + var ns = $.xmlns[id]; + if(typeof(ns) == "undefined") { + throw "Syntax error, undefined namespace prefix '" + id + "'"; + } + return ns; +}; + + +// Update the regex used by $.expr to parse selector components for a +// particular type of selector (e.g. "TAG" or "ATTR"). +// +// This logic is taken straight from the jQuery/Sizzle sources. +// +var setExprMatchRegex = function(type,regex) { + $.expr.match[type] = new RegExp(regex.source + /(?![^\[]*\])(?![^\(]*\))/.source); + if($.expr.leftMatch) { + $.expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + $.expr.match[type].source.replace(/\\(\d+)/g, function(all, num){ + return "\\" + (num - 0 + 1); + })); + } +} + + + +// Modify the TAG match regexp to include optional namespace selector. +// This is basically (namespace|)?(tagname). +// +setExprMatchRegex("TAG",/^((?:((?:[\w\u00c0-\uFFFF\*_-]*\|)?)((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)))/); + + +// Perform some capability-testing. +// +var div = document.createElement("div"); + +// Sometimes getElementsByTagName("*") will return comment nodes, +// which we will have to remove from the results. +// +var gebtn_yields_comments = false; +div.appendChild(document.createComment("")); +if(div.getElementsByTagName("*").length > 0) { + gebtn_yields_comments = true; +} + +// Some browsers return node.localName in upper case, some in lower case. +// +var localname_is_uppercase = true; +if(div.localName && div.localName == "div") { + localname_is_uppercase = false; +} + +// Allow the testing div to be garbage-collected. +// +div = null; + + +// Modify the TAG find function to account for a namespace selector. +// +$.expr.find.TAG = function(match,context,isXML) { + var ns = getNamespaceURI(match[2]); + var ln = match[3]; + var res; + if(typeof context.getElementsByTagNameNS != "undefined") { + // Easy case - we have getElementsByTagNameNS + res = context.getElementsByTagNameNS(ns,ln); + } else if(typeof context.selectNodes != "undefined") { + // Use xpath if possible (not available on HTML DOM nodes in IE) + if(context.ownerDocument) { + context.ownerDocument.setProperty("SelectionLanguage","XPath"); + } else { + context.setProperty("SelectionLanguage","XPath"); + } + var predicate = ""; + if(ns != "*") { + if(ln != "*") { + predicate="namespace-uri()='"+ns+"' and local-name()='"+ln+"'"; + } else { + predicate="namespace-uri()='"+ns+"'"; + } + } else { + if(ln != "*") { + predicate="local-name()='"+ln+"'"; + } + } + if(predicate) { + res = context.selectNodes("descendant-or-self::*["+predicate+"]"); + } else { + res = context.selectNodes("descendant-or-self::*"); + } + } else { + // Otherwise, we need to simulate using getElementsByTagName + res = context.getElementsByTagName(ln); + if(gebtn_yields_comments && ln == "*") { + var tmp = []; + for(var i=0; res[i]; i++) { + if(res[i].nodeType == 1) { + tmp.push(res[i]); + } + } + res = tmp; + } + if(res && ns != "*") { + var tmp = []; + for(var i=0; res[i]; i++) { + if(res[i].namespaceURI == ns || res[i].tagUrn == ns) { + tmp.push(res[i]); + } + } + res = tmp; + } + } + return res; +}; + + +// Check whether a node is part of an XML document. +// Copied verbatim from jQuery sources, needed in TAG preFilter below. +// +var isXML = function(elem){ + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; +}; + + +// Modify the TAG preFilter function to work with modified match regexp. +// This normalises case of the tag name if we're in a HTML document. +// +$.expr.preFilter.TAG = function(match, curLoop, inplace, result, not, isXML) { + var ln = match[3]; + if(!isXML) { + if(localname_is_uppercase) { + ln = ln.toUpperCase(); + } else { + ln = ln.toLowerCase(); + } + } + return [match[0],getNamespaceURI(match[2]),ln]; +}; + + +// Modify the TAG filter function to account for a namespace selector. +// +$.expr.filter.TAG = function(elem,match) { + var ns = match[1]; + var ln = match[2]; + var e_ns = elem.namespaceURI ? elem.namespaceURI : elem.tagUrn; + var e_ln = elem.localName ? elem.localName : elem.tagName; + if(ns == "*" || e_ns == ns || (ns == "" && !e_ns)) { + return ((ln == "*" && elem.nodeType == 1) || e_ln == ln); + } + return false; +}; + + +// Modify the ATTR match regexp to extract a namespace selector. +// This is basically ([namespace|])(attrname)(op)(quote)(pattern)(quote) +// +setExprMatchRegex("ATTR",/\[\s*((?:((?:[\w\u00c0-\uFFFF\*_-]*\|)?)((?:[\w\u00c0-\uFFFF_-]|\\.)+)))\s*(?:(\S?=)\s*(['"]*)(.*?)\5|)\s*\]/); + + +// Modify the ATTR preFilter function to account for new regexp match groups, +// and normalise the namespace URI. +// +$.expr.preFilter.ATTR = function(match, curLoop, inplace, result, not, isXML) { + var name = match[3].replace(/\\/g, ""); + if(!isXML && $.expr.attrMap[name]) { + match[3] = $.expr.attrMap[name]; + } + if( match[4] == "~=" ) { + match[6] = " " + match[6] + " "; + } + if(!match[2] || match[2] == "|") { + match[2] = ""; + } else { + match[2] = getNamespaceURI(match[2]); + } + return match; +}; + + +// Modify the ATTR filter function to account for namespace selector. +// Unfortunately this means factoring out the attribute-checking code +// into a separate function, since it might be called multiple times. +// +var filter_attr = function(result,type,check) { + var value = result + ""; + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value != check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0,check.length+1)===check+"-" : + false; +} + + +$.expr.filter.ATTR = function(elem, match) { + var ns = match[2]; + var name = match[3]; + var type = match[4]; + var check = match[6]; + var result; + // No namespace, just use ordinary attribute lookup. + if(ns == "") { + result = $.expr.attrHandle[name] ? + $.expr.attrHandle[name](elem) : + elem[name] != null ? + elem[name] : + elem.getAttribute(name); + return filter_attr(result,type,check); + } + // Directly use getAttributeNS if applicable and available + if(ns != "*" && typeof elem.getAttributeNS != "undefined") { + return filter_attr(elem.getAttributeNS(ns,name),type,check); + } + // Need to iterate over all attributes, either because we couldn't + // look it up or because we need to match all namespaces. + var attrs = elem.attributes; + for(var i=0; attrs[i]; i++) { + var ln = attrs[i].localName; + if(!ln) { + ln = attrs[i].nodeName + var idx = ln.indexOf(":"); + if(idx >= 0) { + ln = ln.substr(idx+1); + } + } + if(ln == name) { + result = attrs[i].nodeValue; + if(ns == "*" || attrs[i].namespaceURI == ns) { + if(filter_attr(result,type,check)) { + return true; + } + } + if(attrs[i].namespaceURI === "" && attrs[i].prefix) { + if(attrs[i].prefix == default_xmlns_rev[ns]) { + if(filter_attr(result,type,check)) { + return true; + } + } + } + } + } + return false; +}; + + +})(jQuery); +