I'm trying to figure this out, but there's not much information. Which browsers support E4X, and why isn't it more widely adopted?
Which browsers support E4X
Firefox and others based on the Mozilla codebase.
why isn't it more widely adopted?
Because it offers little practical functionality not already covered by existing standards such as DOM.
OK, it's simpler to use than DOM, but as the price for that you don't get access to all the features of XML, and the thoroughly idiotic, needless XML literal/template syntax is a security disaster, making it so authors of even completely static htaccess-protected documents have to worry about working around the feature.
As a simpler method for accessing the results of an XMLHttpRequest, JSON totally won. For full-on XML processing, you still need DOM. For easier document handling, there are selectors, XPath and JS libraries that can do it without having to introduce weird new language syntax.
That doesn't leave much of a niche for E4X. TBH I wish it would die. (ETA: it has now pretty much done so.)
Firefox dropped E4X support in version 16:
E4X is deprecated. It will be disabled by default for content in Firefox 16, disabled by default for chrome in Firefox 17, and removed in Firefox 18. Use DOMParser/DOMSerializer or a non-native JXON algorithm instead.
According to w3schools, "Firefox is currently the only browser with relatively good support for E4X."
You could try XPath instead. Although XPath isn't cross-browser there are several Javascript solutions for it like this jQuery plugin.
EDIT
You could actually use jQuery without a plugin for this:
$('<xml><some><code>code</code><tag>text</tag></xml></xml>').find('some > code').text()
I have developed a babel plugin that adds E4X basic support to all browsers via babel compilation.
https://www.npmjs.com/package/babel-plugin-transform-simple-e4x
You can also use the npm simple4x library to parse xml strings to a XML like object.
https://www.npmjs.com/package/simple4x
The plugin transpiles the following E4X:
var fooId = 'foo-id';
var barText = 'bar text';
var xml =
<xml>
<foo id={fooId}>
{barText}
</foo>
</xml>;
To the following JavaScript:
var XML = new require("simple4x");
var fooId = 'foo-id';
var barText = 'bar text';
var xml = new XML("<xml><foo id=\"" + fooId + "\">" + barText + "</foo></xml>");
Related
I was just forced into a browser upgrade (IE8 to IE11) while in the middle of testing. I've lost some essential functionality with some javascript that suddenly doesn't work in my .NET site.
This section of the code was written when I was in grade school, so I'm not extremely familiar with it, but what seems to be the problem is a call to form.all. I have to assume that call was built into javascript at some point - there's no definition for it in the code.
There are 7 "if statements" that use form.all and they are all written the same way:
if(form.all(cTag + "PersonNum") != null)
form.all(cTag + "PersonNum").value = personNumber;
The error:
JavaScript runtime error: Object doesn't support property or method 'all'
In newer versions of JavaScript, is there a version of form.all that performs the same action? All I really need is for someone to point me in the right direction.
A weird note: the same JavaScript code IS working in production on IE11
EDIT Ok, I found a line that was minimized. It looks like form is a created variable.
var form = document.forms(0);
EDIT2 Compatibility view/mode was the solution after all. I had added our production site's domain to the compatibility list and didn't think about it; adding 'localhost' fixed the issue. You just have to set it to the right domain first for it to work :)
Check the browser compatability mode when your running in production it's probally on IE8.
You can use obj.getElementsByTagName("*")
You could also add an All method to the prototype if it's not there.
IE introduced an all property for certain DOM objects (e.g. document) but it was never part of any W3C standard. It allowed access to DOM objects by name or ID using:
var element = document(elementNameOrID);
or
var element = document[elementNameOrID];
that is, it is a property that could use the same syntax as a method. Neat. Some other browsers supported it for compatibility, but it pretty much went out of use with IE 6 (not sure when IE started supporting getElementById, I think it was IE 5). But IE continued to think name and ID attributes were the same thing until IE 8 in standards mode.
Support for all has been dropped from IE 11 in standards mode.
If form is a reference to a form element, and cTag + "PersonNum" is the name of a form control, then the simplest fix is to change:
form.all(cTag + "PersonNum").value
to
form[cTag + "PersonNum"].value
which takes advantage of named form controls being made properties of the form that contains them. This behaviour is standardised and supported by browsers from the very beginning (i.e. every where) and is future proof (it's not going to change).
My User defined sort function does not work in IE 8.
Object doesn't support property or method 'indexOf'
roles_store.sort([{
sorterFn: function(v1, v2) {
var order = ['read-only', 'user', 'admin', 'super'],
v1o = order.indexOf(v1.get('role_name')),
v2o = order.indexOf(v2.get('role_name'));
return v1o < v2o ? -1 : 1;;
}
}]);
The following link shows a workaround:
How to fix Array indexOf() in JavaScript for Internet Explorer browsers
I tried replacing indexof with Array.prototype.indexOf
v2o = order.Array.prototype.indexOf (v2.get('role_name'));
I apologize if I missed something here
IE 8 is a little old and it includes an old javascript version. It doesn´t have a lot of very useful methods that we use everyday. I recommend to include the tiny Array prototype extensions library (link). That library allows you to use all the methods (for arrays) that all new browsers (with newer javascript version) include.
You also can use the Extjs methods as Evan suggests (they work well) but you have to have that in mind all the time and most of the snippets and code samples that you find in internet or this site won´t run (you will have to translate them to use extjs methods). Another problem is that your code will works ok in Chrome and FF but not in IE if you not take care.
It is much more easy and safe to include the extensions that I recommend you, that´s what we did in our own project and it was a great solution.
Use Ext.Array.indexOf, it defers to the native indexOf where possible.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Array-method-indexOf
I want to build a library in JavaScript/JScript/ECMAScript...whatever you want to call it, which will target modern standards (HTML5, CSS3, ESv5) with that in mind, any browser that supports the standard! Now I know there are already plenty of useful libraries out there, i.e. jQuery and MooTools. Of course they're great and I already use those where necessary, but I should not be forced to jump on the same bandwagon as every other developer just because it's popular!
So for the sake of the following questions, let us not concern ourselves with 3rd party libraries such as jQuery and MooTools. Lets get down to nitty-gritty JavaScript/JScript/ECMAScript.
Firstly, I asked a question prior to this (What's the difference between JavaScript, JScript & ECMAScript?), as I did not know what the difference was.
Thankfully I concluded the following:
ECMAScript is the language specification. JavaScript and JScript are dialects of ECMAScript.
JavaScript is Mozilla's implementation of ECMAScript.
JScript is Microsoft's implementation of ECMAScript.
OK, that was a nice simple answer wasn't it? But here's some questions which stem from that:
is "JavaScript" supported in non-mozilla browsers, and to what extent?
is "JScript" supported in non-microsoft browsers, and to what extent?
Based on those two questions, I did a little digging and ran a simple test on IE9, FF14 and GC19.
Here is the test code:
<!DOCTYPE html>
<html>
<head>
<title>HTML 5 Template</title>
<script language="JavaScript1.3">
jsver = "1.3";
</script>
<script language="JavaScript1.4">
jsver = "1.4";
</script>
<script language="JavaScript1.5">
jsver = "1.5";
</script>
<script language="JavaScript1.6">
jsver = "1.6";
</script>
<script language="JavaScript1.7">
jsver = "1.7";
</script>
<script language="JavaScript1.8">
jsver = "1.8";
</script>
<script type="text/javascript">
document.write("<B>Your browser supports JavaScript version " + jsver + ".</B>")
</script>
</head>
<body>
</body>
</html>
The results were: IE9 = JSv1.3, FF14 = JSv1.8, GC19 = JSv1.7
OK, then I ran this test, which tests for ECMAScript version 5 support:
http://kangax.github.com/es5-compat-table/#showold
Again using the same browsers (IE9, FF14, GC19), ESv5 seems to be fairly well supported!
Now comes the tricky bit! I come from a Microsoft background, and write software using languages like C#, ASP.NET etc, so naturally, my IDE of choice is Visual Studio (currently 2010). When I look through the JavaScript intellisense I see things like ActiveXObject, Array, Object, etc.
Should I trust VS2010's intellisense?
Where can I find a reference of ESv5 supported objects and features?
How do I detect if a browser supports a particular object or feature?
Is there anything better than VS2010 out there that will help me write compliant ESv5 code?
Is it safe to override implementations of existing objects like Object, Number, Boolean etc, or should I just extend the existing implementation?
Finally, concerning myself with jQuery. Let's say I can't be bothered to write the core compliancy & functionality myself, can I just write my library to sit on top of jQuery...or is this just a copout?
1) Nope. Certainly it won’t restrict to just valid ECMAScript.
2) http://kangax.github.com/es5-compat-table/ is always useful.
3) You can just check to see if it’s defined. E.g.
typeof(Array.isArray) === 'function'; // true in newer browsers, false in IE8
4) Your best bet is to read the spec! Using "use strict"; in your code will also catch some classes of errors and it good practise. More explanation on strict mode at http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
5) Certainly I wouldn’t replace the original objects. If you’re going to extend properties I’d first double-check that a compliant implementation doesn’t already exist. E.g. PrototypeJS added (before browsers implemented it) a document.getElementsByClassName. When browsers started implementing it natively they found out that sites using Prototype were still using the slow JS-based version. The fix was just to wrap Prototype’s definition in a if (document.getElementsByClassName == undefined) { }
2) I find the Overview you provided pretty good. What else do you want?
3) A good library to even out the differences between the browser is ES5-shim. It autodetects the features and provides shims for the browsers who lack support.
4) Always use "use strict"; and a have good editor of your choice which has some kind of code-highlighting and perhaps code-completion. I use the browser consoles or firefox scratchpad (silly name for a good tool) for quick hacking sessions and put it all together in notepad++ (= the IDE of your choice).
5) Augmenting the native javascript objects has been debated a lot and has pros and cons. Prototype and MooTools go this way. jQuery takes the other way and provides a separate object for that. I personally prefer to leave the native (and especially host) objects alone and have your own namespace with the functions you need.
I would like to use javascript XPaths in a web app using exslt extensions, but I can't figure out how to do this.
Pretend I've got an html doc with some divs in it. I want to run this:
namespaces={'regexp':'http://exslt.org/regular-expressions'};
result = document.evaluate(
"//div[regexp:test(.,'$')]",
document,
function(ns){
return namespaces.hasOwnProperty(ns) ? namespaces[ns] : null;
},
XPathResult.ANY_TYPE,
null);
Only that results in an invalid XPath expression exception in evaluate. I'm using chrome.
Is there anything else I need to do to make this stuff work? I see on exslt.org that there are implementations for javascript, but how do I make sure those are available? Do I need to insert my javascript into a namespaced script element in the dom or something insane?
UPDATE
If this isn't possible directly using browser dom + javascript and xpath, would it be possible to write XSLT using exslt extensions in the browser to simulate document.evaluate (returning a list of elements that match the xpath)?
I don't think the default browser XPath implementation supports EXSLT. The javascript support mentioned on the EXSLT page is likely about how you can provide your own implementation of the exslt function using in-browser.javascript. Here's one example I was able to find very quickly.
In Firefox, for example, you can have Saxon-B as an extension to run XSLT2.0 and Saxon-B has built-in support for exslt (unlike Saxon-HE), though you will likely be better off just using XSLT/XPath 2.0 features. Here's the regular expression syntax, for example. That said, however, relying on a Mozilla Saxon-B extension isn't something that will help you with Chrome or other browsers for that matter.
With that said I don't think you can find a cross-browser solution to use EXSLT extensions in your XPath. The conformance section of the DOM Level 3 XPath calls for XPath 1.0 support and doesn't mention EXSLT. The INVALID_EXPRESSION_ERR is said to be thrown:
if the expression has a syntax error or otherwise is not a legal expression according to the rules of the specific XPathEvaluator or contains specialized extension functions or variables not supported by this implementation.
Finally, here's an open bugzilla ticket for Firefox to open up EXSLT support for their DOM Level 3 XPath implementation. It seems to be sitting there in NEW status since 2007. The ticket says that:
Currently Mozilla gives an exception "The expression is not a legal expression." even if a namespace resolver correctly resolving the EXSLT prefixes to the corresponding URLs is passed in. Here's the test case.
--
If you don't mind me asking, what exactly you wanted to use the regex for? Maybe we can help you get away with a combination of standard XPath string functions?
--
UPDATE You can build an XPath runner via XSLT (like you're asking in the update to your question) but it won't return the nodes from the source document, it will return new nodes that look exactly the same. XSLT produces a new result tree document and I don't think there's a way to let it return references to the original nodes.
As far as I can tell, Mozilla (and Chrome) both support XSLT not only for XML documents loaded from external sources, but also for DOM elements from the document being displayed. The XSLTProcessor documentation mentions how tranformToFragment(), for example, will only produce HTML DOM objects if the owner document is itself an HTMLDocument, or if the output method of the stylesheet is HTML.
Here's a simple XPath Runner that I built testing out your ides:
1) First you would need an XSLT template to work with.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:regexp="http://exslt.org/regular-expressions"
extension-element-prefixes="regexp">
<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
I started building it in the JavaScript using the document.implementation.createDocument APi but figured it would be easier to just load it. FF still supports document.load while Chrome only lets you load stuff using XHR. You would need to start your Chrome with --allow-file-access-from-files if you want to load files with XHR from your local disk.
2) Once we have the template loaded we would need to modify the value of the select attribute of the xsl:copy-of instruction to run the XPath we need:
function runXPath(xpath) {
var processor = new XSLTProcessor();
var xsltns = 'http://www.w3.org/1999/XSL/Transform';
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET", "xpathrunner.xslt", false);
xmlhttp.send(null);
var transform = xmlhttp.responseXML.documentElement;
var copyof = transform.getElementsByTagNameNS(xsltns, 'copy-of')[0];
copyof.setAttribute('select', xpath);
processor.importStylesheet(transform);
var body = document.getElementById('body'); // I gave my <body> an id attribute
return processor.transformToFragment(body, document);
}
You can now run it with something like:
var nodes = runXPath('//div[#id]');
console.log(nodes.hasChildNodes());
if (nodes.firstChild) {
console.log(nodes.firstChild.localName);
}
It works great for "regular" XPath like that //div[#id] (and fails to find //div[#not-there]) but I just can't get it to run the regexp:test extension function. With the //div[regexp:test(string(#id), "a")] it doesn't error out, just returns empty set.
Mozilla documentation suggests their XSLT processor support EXSLT. I would imagine they are all using libxml/libxslt behind the scenes anyway. That said, I couldn't get it to work in Mozilla either.
Hope it helps.
Any chance you can get away with jQuery regexp? not likely to be helpful for your XPath builder utility but still a way to run regexp on HTML nodes.
I have a handful of code that uses the DOM to parse and traverse some XML data. It works fine on Gecko and WebKit but, of course, IE absolutely chokes on it. Is there a library for an XML DOM that supports:
getAttributeNS
localName
namespaceURI
Support for IE7 is about as far back as I need to go.
You can use jQuery to safely and easily parse XML in Internet Explorer. This tutorial Easy XML Consumption using jQuery will give you a more in-depth information on how you can do it.
Not sure if you want to go this route, but this can be done with MSXML using their nonstandard way of doing things. MSXML 3.0 comes with IE 6 and later.
I haven't actually done this ;-) but this might be what you need:
IXMLDOMNamedNodeMap.getQualifiedItem looks like getAttributeNS
http://msdn.microsoft.com/en-us/library/ms757075.aspx
IXMLDOMNode has a namespaceURI property.
http://msdn.microsoft.com/en-us/library/ms763813.aspx
IXMLDOMNode.baseName looks like localName
http://msdn.microsoft.com/en-us/library/ms767570.aspx