Monday, June 28, 2010

SCRIPT.src vs. getAttribute("src") and magic 4 for MSIE

// Lets have uri:
http://localhost:8080/a/b/c/script.js

//1. popular (incorrect) way to find URI for current script (inside the script code)
var script_src = (scripts = head[0].getElementsByTagName("SCRIPT"))[scripts.length - 1].src;

//2. popular trick to "resolve" uri to another script in the same "directory"
// src becomes:
// http://localhost:8080/a/b/c/script.js/../script2.js
// which is then transformed by browsers in actual http request to
// http://localhost:8080/a/b/c/script2.js


however when combined together, it can turn deadly in Cross-Browser code
since .src returns "dots removed" in FF

http://localhost:8080/a/b/c/script2.js

and raw value in MSIE 7.0

http://localhost:8080/a/b/c/script.js/../script2.js


So here comes the another magic constant 4 in getAttribute("src",4) for MSIE ;-), but ? it does not work ?! (now tested in MSIE 8)
http://msdn.microsoft.com/en-us/library/ms536429(v=VS.85).aspx
so you have to use .src !

As far as I know even jQuery does not have fix for this,
even if they have for getAttribute("href",2)

Edited in 2011:
Confused ? me as well. I have to retest all this because MSIE 8 seems to somehow work with .src and not work with getAttribute("src,4").
Work means returning "expanded" and "normalized" uri.

Wednesday, June 23, 2010

isDialog(window) and window.dialogArguments

How to do detection if window was opened with
shoModalDialog or showModelessDialog vs. with the window.open or other method.

Code was ugly because of non null opener returned in non MSIE browsers
and tricky window.dialogArguments if undefined and null values where passed to showModalDialogMethod

This is my proposal for reliable version test isDialog(window) tested in FF,MSIE 7,Chrome and Safari (originally it was 6 lines long with browser sniffing)

return "dialogArguments" in window;

Thanx http://perfectionkills.com/for inspiration.

Thursday, June 17, 2010

Link of the day ! "DOM Deviations", sorry "Normative Variations"

The following subsections detail the normative variations from MUST requirements in [DOM Level 3 - Core].

http://msdn.microsoft.com/en-us/library/ff460357(v=VS.85).aspx


Or even better:
Internet Explorer Standards Support Documents

http://msdn.microsoft.com/en-us/library/ff405926(v=VS.85).aspx

Wednesday, June 16, 2010

Firefox/3.5.6 window.onerror (MDC docs buggy as well)

https://developer.mozilla.org/en/DOM/window.onerror#Parameters
funcRef is a reference to a function. When the function returns true, this prevents the firing of the default event handler. Function parameters:
Error message (string)
Url where error was raised (string)
Line number where error was raised (number)
Question is What the "raised" means ?
In MSIE it means "thrown" (that is the word). In FF it means where new Error() was called.

Tested on:
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)


Testcase available for those interesed (mail me).

You may be interesed in this as well:
https://bugzilla.mozilla.org/show_bug.cgi?id=355430


https://developer.mozilla.org/en/DOM/window.onerror#Parameters
funcRef is a reference to a function. When the function returns true, this prevents the firing of the default event handler. Function parameters:
Error message (string)
Url where error was raised (string)
Line number where error was raised (number)

The problem: What the "raised" means ?

In MSIE it means "thrown" (that is the word). In FF it means where new Error() was called.

Tested on:
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)


Testcase available for those interesed (mail me).

You may be interesed in this as well:
https://bugzilla.mozilla.org/show_bug.cgi?id=355430

I have had a look at "solution" presented here:
http://github.com/emwendelin/javascript-tacktrace#readme but this
Some people recommend just assigning it to window.onerror:

window.onerror = function() {
alert(printStackTrace().join('\n\n'));
}

will not work in FF, just because of mentioned stack bug.

So all you will learn with the stacktrace.js sample is:

run(null)
printStackTrace
onerror

That your on error was called and it called printstacktrace and run.
You will not learn who called your onerror handler.

Monday, June 14, 2010

W3 Document.textContent vs. MSXML Document.text and MSDN docs

w3 says that .textContent for DOCUMENT_NODE should be null.
Closest MS implementation (MSXML .text) documented in MSDN claims:
NODE_DOCUMENT
Returns a string representing the value of the node.
This is the concatenated text of
all subnodes with entities expanded.
But what is subnodes and what is text ?
<?xml version="1.0" encoding="utf-8" ?>
<!-- Document level comment -->
<!-- TODO: NOTATION -->
<!DOCTYPE root [
    <!ENTITY ent1 "expanded ent1">
]>
<?pi1 ?>
<root attribute="attribute.value">
    element.text.1
    <e1><![CDATA[cdata.content]]></e1>
    <e2><!--comment.content--></e2>
    <e3>&ent1;</e3>
    element.text.2
</root> 
Remarks section clarifies something:
When concatenated, the text represents the contents of text or CDATA nodes. All concatenated text nodes are normalized according to xml:space attributes and the value of the preserveWhiteSpace switch. Concatenated CDATA text is not normalized. (Child nodes that contain NODE_COMMENT and NODE_PROCESSING_INSTRUCTION nodes are not concatenated.) .text trims the whitespace on the edges of the result, and "normalizes" \r\n => \n, but otherwise just concatenates text.
Retrieves and sets the string representing the text contents of this node or the concatenated text representing this node and its descendants.
For more precise control over text manipulation in an XML document, use the lower-level nodeValue property, which returns the raw text associated with a NODE_TEXT node.
For this sample it returns:
element.text.1 cdata.content expanded ent1 element.text.2
Both comments skipped, OK, but I still, miss the text of my NODE_ENTITY.
If requested ditectly NODE_ENTITY.text returns:
expanded ent1
So I would expect:
expanded ent1 element.text.1 cdata.content expanded ent1 element.text.2
Why is NODE_ENTITY.text missing from NODE_DOCUMENT.text ? Maybe because it is inside NODE_DOCUMENT_TYPE which claims to return .text as "" ? Or because :text", does not mean text but nodeValue which is defined as null for both NODE_DOCUMENT_TYPE and NODE_ENTITY.

Results:
From my quick tests Document.text behaves the same as Document.documentElement.text. If anyone can show, how the may differ I would be pleased. Until then, considered as bad design, useless w3 deviation and insufficent documentation.

Wednesday, June 9, 2010

MSXML.createNode method (docs,design,standards?)

http://msdn.microsoft.com/en-us/library/ms757901(VS.85).aspx
A string defining the namespace URI. If specified, the node is created in the context of
the namespaceURI parameter with the prefix specified on the node name.
If the name parameter does not have a prefix, this is treated as the default namespace.

The marked part may be a bit problematic to interpret.
In the reality it means that createNode will create unprefixed element or attribute and
produce xmlns="ns" declaration.

This is fine for elements because of xmlns scoping.
However this leads to troubles if creating
unprefixed-namespaced-attribute on unprefixed-namespaced-element with different namespace,
and also if creating
prefixed-namespaced-attribute on prefixed-namespaced-element with different namespace and same prefixes.
var root = d.createNode(1, "root", "nsRoot"),
    ch1 = d.createNode(1, "p:child", "nsChild"),
    ch2 = d.createNode(1, "child", "nsChild"),
    a1 = d.createNode(2, "p2:a1", "nsAttr"),
    a2 = d.createNode(2, "a2", "nsAttr");

root.appendChild(ch1);
root.appendChild(ch2);
ch2.setAttributeNode(a1);
ch2.setAttributeNode(a2);
The last line will fail, with "bit problematic to interpret" error,
showing authors misinterpretation of namespace and prefixe terms ;-)

There was a Namespace conflict for the '' Namespace.

Actualy there was a conflict for '' prefix between nsChild and nsAttr namespaces.

XML without last line will look like this:
<root xmlns="nsRoot">
    <p:child xmlns:p="nsChild"/>
    <child xmlns="nsChild" xmlns:p2="nsAttr" p2:a1=""/>
</root>

Try to rewrite this code with createElementNS and createAttributeNS in different browsers.
Some are able to autogenerate prefixes if already taken by another namespace, some produce funny results.

MS is lucky not to declare http://www.w3.org/TR/DOM-Level-2-Core/ compliance, however the docs are confusing and
prefix colisions unsolved.

Another silly decision is that namespaceURI does not accept null.
The closes standardized method (DOM2 Level createElementNS) speaks abou null values, and all browsers implement
both null and "" as "unqualified".

Construction without new

inspired by jQuery
(function(window, undefined) {

 function XElement(node) {
  /// 
  return new XElement.prototype.cnstr(node);
 }
 XElement.prototype =
 {
  cnstr: function(node) {
   this.node = node;
  }
 };
 XElement.prototype.cnstr.prototype = XElement.prototype;
 window.XElement = XElement;
})(window);

Tuesday, June 8, 2010

Exporting module functions to window and "Object doesn't support this property or method"

Try to gues what you get from each sample call in MSIE 7.0 ?

//-------------------------------------------------------------------------
// sample1: jQuery style of export
(function(window, undefined) {
    var query = function() {
        throw new Error("hop");
    }
    window.query = query;

})(window);


window.onload = function() {
    try {
        query();
    } catch (ex) {
        //???
        alert(ex.message);
    }
}
//-------------------------------------------------------------------------// sample1: exporting to "custom namespace" not window
var ns = {};
(function(window, undefined) {
    var query = function() {
        throw new Error("hop");
    }
    window.query = query;

})(ns);

window.onload = function() {
    try {
        ns.query();
    } catch (ex) {
        //???
        alert(ex.message);
    }
}
//-------------------------------------------------------------------------// plain old "global scope method"

var query = function() {
    throw new Error("hop");
}
window.onload = function() {

    try {
        query();
    } catch (ex) {
        //???
        alert(ex.message);
    }
}

Final fix ? export,import


(function(window, undefined) {
    var query = function() {
        throw new Error("hop");
    }
    window.query = query;
})(window);


window.onload = function() {
    var query = window.query;
    try {
        query();
    } catch (ex) {
        //???
        alert(ex.message);
    }
}

Monday, June 7, 2010

node.setAttributeNS(namespaceURI, qualifiedName, value)

When trying to implement this missing method in MSXML,
several interesing
inconsistencies in other browsers apeared,
all claim the native support for this method.

Pseudopcode:

set("ns1","a:a","1")
old=getAttributeWithXPath
set("ns1","b:a","2")
new=getAttributeWithXPath
print compare pointers
print new.nodeName
print new.value
print serialized xml


MSXML 6.0

result:false
p2:a
2
xmlns:p2="ns" p2:a="2"


Firefox/3.5.6

result:true
p1:a
2
p2:a="2" xmlns:p2="ns"

Safari/531.22.7

result:true
p1:a
1
p1:a="2" xmlns:p1="ns"


Chrome/5.0.375.55

result:true
p1:a
2
p1:a="2" xmlns:p1="ns"

Of course there is always an excuse:
http://www.w3.org/TR/DOM-Level-2-Core/core.html
Note: DOM Level 1 methods are namespace ignorant. Therefore, while it is safe to use these methods when not dealing with namespaces, using them and the new ones at the same time should be avoided. DOM Level 1 methods solely identify attribute nodes by their nodeName. On the contrary, the DOM Level 2 methods related to namespaces, identify attribute nodes by their namespaceURI and localName. Because of this fundamental difference, mixing both sets of methods can lead to unpredictable results. In particular, using setAttributeNS, an element may have two attributes (or more) that have the same nodeName, but different namespaceURIs. Calling getAttribute with that nodeName could then return any of those attributes. The result depends on the implementation. Similarly, using setAttributeNode, one can set two attributes (or more) that have different nodeNames but the same prefix and namespaceURI. In this case getAttributeNodeNS will return either attribute, in an implementation dependent manner. The only guarantee in such cases is that all methods that access a named item by its nodeName will access the same item, and all methods which access a node by its URI and local name will access the same node. For instance, setAttribute and setAttributeNS affect the node that getAttribute and getAttributeNS, respectively, return.