href attribute set, javascript sees as empty string - javascript

I am experiencing odd behaviour in Chrome (v43.0.2357.134) whereby I am reading an anchor element's .href attribute, but in specific circumstances its value is an empty string.
I would like the .href value to be populated on all anchors.
Issue
Specifically, this is what is being observed:
//Bad (unwanted) behaviour
var currentElem = ; //Code to pick out an anchor element
console.info(currentElem.href); //"" (empty string)
console.info(currentElem.getAttribute('href'); //"path/to/other/page.html"
Edited to add/clarify: Note that in this screenshot, at the point of reaching the fourth line of code the value of nextPageUri is an empty string (otherwise would not have reached the debugger; line). The fifth line then populates nextPageUri with the .getAttribute('href') value, hence the value showing next to line two.
This is what is (correctly) seen within Firefox, and on the first TWO DOMs via Chrome:
//Good (desired) behaviour
var currentElem = ; //Code to pick out an anchor element
console.info(currentElem.href); //"http://example.org/root/dir/path/to/other/page.html"
console.info(currentElem.getAttribute('href'); //"path/to/other/page.html"
Background
Context: This is within a script to inline multiple pages of search results to a single page, and the anchor elements are located within a DOM retrieved via xmlHttpRequest. The code runs perfectly via Firefox for >100 pages.
Confusingly, the incorrect behaviour described above only occurs on the third and subsequent requests in the Chrome browser.

This is an issue with Chromium/Blink-based browsers: if you use DOMParser to parse string into a document, href properties with relative URI (i.e. doesn't start with http[s]) will be parsed as empty string.
To quote tkent from Chromium issue 291791:
That's because a document created by DOMParser doesn't have baseURI. Without baseURI, relative URI references are assumed as invalid.
Same thing happens if you use createHTMLDocument. (Chromium issue 568886)
Also, based on this test code posted by scarfacedeb on Github, src properties also exhibit the same behavior with relative URIs.
As you have pointed out, using getAttribute() instead of the dot notation works fine.

Chrome's "element.href" doesn't act any differently on the 3rd try than it does on the first 2 -- you mentioned that you are paginating, when this error happens. how does the "href" attribute on the Next Page link get set each time you arrive at the page? It seems likely that your code to evaluate the element's href attribute is simply running before the href is set -- as evidenced by your debugger being able to evaluate it after a pause.
Try and reproduce this issue in a plunkr.

I know you're checking if nextPageUri is empty.
But, could you try always using
nextPageUri = currentElem.getAttribute('href');
and see if that works?
I experienced a similar problem using a DOMParser for translating text/html pages coming from ajax requests and, after that, finding href's of <a> elements inside it.
For instructions purpose, this is how I'm using the parser
var parser = new DOMParser();
$.ajax({....}).done(function(request){
var page = parser.parseFromString(request, 'text/html');
});
Test yourself
If you want to test the behaviour of .href and .getAttribute("href") yourself, please run this code at chrome dev tools console:
parser = new DOMParser(); // create your DOMParser
// the next line creates a "document" element with an <a> tag inside it
parsed_page = parser.parseFromString('click here', 'text/html');
link = parsed_page.getElementsByTagName('a')[0]; // locate your <a> tag
link.href; // this line returns ""
link.getAttribute('href'); // this line returns "test"

Related

Error using built version of Dojo (but not the uncompressed source)

I noticed something weird when using the uncompressed source of Dojo our code runs normally without error. I tried these two from the archives so far
dojo-release-1.10.6-src and dojo-release-1.10.8-src
However when I switch to the built versions, either
dojo-release-1.10.6 or dojo-release-1.10.8
There is an error that occurs when using dojo.query
TypeError: root.getElementsByTagName is not a function
My function call looks like this
var dom_frag = domConstruct.toDom(response);
var title = dojo.query(".accordion_title", dom_frag)[0];
where response contains HTML string. (too long to post here)
EDIT: Image of debugger showing contents of 'dom_frag'
Ok, have you checked to see if the dom_frag variable is a single dom node? If the dom fragment is multiple nodes, then the dojo.query won't work, because it needs to search the children of a single dom node.
To solve this, try wrapping the toDom contents with a single node... like so:
var dom_frag = domConstruct.toDom("<div>"+response+"</div>");
var title = dojo.query(".accordion_title", dom_frag)[0];
This is, of course, a bit of a hack... but if you can't guarantee that the response will end up a single node, then you need to do it.
Make sure your root is actually a DOM element as:
the Element.getElementsByTagName() method returns a live
HTMLCollection of elements with the given tag name. The subtree
underneath the specified element is searched, excluding the element
itself. Ref.

Why creating the elements with custom tags adds the xml namespace in the outerHTML in IE9 or 10 until the .find() method is called?

I have a jsfiddle that demonstrates the question:
http://jsfiddle.net/H6gML/8/
$(document).ready(function() {
// this seems fine in IE9 and 10
var $div = $("<div>");
console.log("In IE, this <div> is just fine: " + $div[0].outerHTML);
// this is weird in IE
var $test = $("<test>");
console.log("However, this <test> has an xml tag prepended: \n"
+ $test[0].outerHTML);
$test.find("test");
console.log("Now, it does not: \n" + $test[0].outerHTML);
console.log("Why does this behave this way?");
});
Why does this happen? It doesn't happen in Chrome or Firefox. Is there a better way to fix this than to call .find("test") on the object?
Edit
To clarify, I'm not asking why the xml tag is added, rather, I'm wondering why the .find() call get's rid of it. It doesn't make sense to me.
Why does this happen? It doesn't happen in Chrome or Firefox. Is there a better way to fix this than to call .find("test") on the object
It is the IE causing the issue while doing document.createElement on an unknown html element type. It thinks it is an XML node and adds the xml namespace prefixed <?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" />. Instead if you try to make it explicit to mention that it is an html element, this issue doesn't happen.
Try:
var $test = $("<html><test/></html>");
The issue no longer occurs.
To clarify, I'm not asking why the xml tag is added, rather, I'm wondering why the .find() call get's rid of it. It doesn't make sense to me.
Now, when you do a find, jquery internally uses context.getElementsByTagName or (similar based on the type whether it is a class or a tag or id etc..) which means it does this operation on the element test. So in IE when you do that it probably internally resolves the fact that you are trying to perform the operation on an html element and not an xml element and it changes the document type for the underlying context(But i don't know why it changes the parent context though rather than just returning a match). You can check this out by this simple example as well.
var $test = document.createElement("test");
console.log("However, this <test> has an xml tag prepended: \n"
+ $test.outerHTML);
$test.getElementsByTagName("test");
console.log("Now, it does not: \n" + $test.outerHTML);
Demo
Update
Here is a documented way of defining the custom elements
The custom element type identifies a custom element interface and is a sequence of characters that must match the NCName production and contain a U+002D HYPHEN-MINUS character. The custom element type must not be one of the following values:
annotation-xml,
color-profile,
font-face,
font-face-src,
font-face-uri,
font-face-format,
font-face-name,
missing-glyph
So according to this had your tag name been somename-test ex:- custom-test IE recognizes it and it works as expected.
Demo

ie6/7 script tag population giving "unexpected call to method or property access"

I use AJAX to get the content of a script, and then use the following code:
var scr = document.createElement('script');
scr.appendChild(document.createTextNode(script)); // ***
document.getElementsByTagName('head')[0].appendChild(scr);
Where script is astring populated from AJAX. This works fine in IE9, Chrome and Firefox. However, in IE6 and 7 I get an error:
Unexpected call to method or property access
IE gives the number of the the line indicated with the // ***.
Although there are multiple other questions about this, none of the appear to address this precise issue.
Older IE's do not accept child nodes in script elements ( or in style and option elements, but that's another two questions).
You can set the script element's text property instead.
(scripttext is a string of, well, script text.)
var scr = document.createElement('script');
if(window.addEventListener)scr.appendChild(document.createTextNode(script))
else scr.text=scripttext;
document.getElementsByTagName('head')[0].appendChild(scr);
If you already have the code in a string, why make a script tag out of it? Can't you just call eval(script) on it. Won't that do the same thing?
document.getElementsByTagName('head')[0]*;*.appendChild(scr);
Why did you put a semicolon here?

This javascript works in every browser EXCEPT for internet explorer!

The webpage is here:
http://develop.macmee.com/testdev/
I'm talking about when you click the ? on the left, it is supposed to open up a box with more content in it. It does that in every browser except IE!
function question()
{
$('.rulesMiddle').load('faq.php?faq=rules_main',function(){//load page into .rulesMiddle
var rulesa = document.getElementById('rulesMiddle').innerHTML;
var rules = rulesa.split('<div class="blockbody">');//split to chop off the top above rules
var rulesT = rules[1].split('<form class="block');//split to chop off below rules
rulesT[0] = rulesT[0].replace('class=','vbclass');//get rid of those nasty vbulletin defined classes
document.getElementById('rulesMiddle').innerHTML = rulesT[0];//readd the content back into the DIV
$('.rulesMain').slideToggle();//display the DIV
$('.rulesMain').center();//center DIV
$('.rulesMain').css('top','20px');//align with top
});
}
IE converts innerHTML contents into upper case, so you probably are not able to split the string this way, as string operations are case sensitive. Check what the contents really looks like by running
alert(rulesa);
Andris is right. And that's not all. It'll also throw away the quotes in attributes.
It is completely unreliable to make any assumptions about the format of the string you get from innerHTML; the browser may output it in a variety of forms — some of which, in IE's case, are not even valid HTML. The chances of you getting back the same string that was originally parsed are very low.
In general: HTML-string-hacking is a shonky waste of time. Modify HTML elements using their node objects instead. You seem to be using jQuery, so you've got loads of utility functions to help you.
In any case you should not be loading the whole HTML page into #rulesMiddle. It includes a load of scripts and stylesheets and other header nonsense that can't go in there. jQuery allows you to pick which part of the document to insert; you seem to just want the first .blockbody element, so pick that:
$('#rulesMiddle').load('faq.php?faq=rules_main .blockbody:first', function(){
$('#rulesMiddle .blockrow').attr('class', '');
$('.rulesMain').slideToggle();
$('.rulesMain').css('top', '20px');
});
My IE debugger throws an error on your script when I click that button. On this line:
var rulesT = rules[1].split('<form class="block');//split to chop off below rules
IE stops processing the Javascript and says '1' is null or not an object
Don't know if you solve it, but it work's on my Ugly IE ... (its an v8)
Btw: It's me, or does pop-up widows wen open are really, really, really slowing down that platform ?

ie8 var w= window.open() - "Message: Invalid argument."

I have a site that has an IE8-only problem:
The code is:
var w = window.open(urlstring, wname, wfeatures, 'false');
The error is:
Message: Invalid argument.
Line: 419
Char: 5
Code: 0
URI: http://HOSTNAME/js_context.js
I have confirmed the line number of the code (the "Line" and "URI" are correct), and I understand in later versions of IE8, this is considered accurate.
I have checked all the incoming parameters in the call by dumping alerts, and they all look valid.
This problem does not happen on FF (probably 3).
UPDATE:
The problem appears to be in using assigning the result of window.open() when doing "var w". When I split the line into two statements it works in IE8.
UPDATE2:
Based on:
http://javascript.crockford.com/code.html
When a function is to be invoked
immediately, the entire invocation
expression should be wrapped in parens
so that it is clear that the value
being produced is the result of the
function and not the function itself.
This is not exactly what is going on here, but I found that applying the principle solved the problem, in IE8's compatability mode.
var w = (window.open(urlstring, wname, wfeatures, false));
This is an old posting but maybe still useful for someone.
I had the same error message. In the end the problem was an invalid name for the second argument, i.e., I had a line like:
window.open('/somefile.html', 'a window title', 'width=300');
The problem was 'a window title' as it is not valid. It worked fine with the following line:
window.open('/somefile.html', '', 'width=300');
In fact, reading carefully I realized that Microsoft does not support a name as second argument. When you look at the official documentation page, you see that Microsoft only allows the following arguments, If using that argument at all:
_blank
_media
_parent
_search
_self
_top
IE is picky about the window name argument. It doesn't like spaces, dashes, or other punctuation.
When you call window.open in IE, the second argument (window name) has to be either one of the predefined target strings or a string, which has a form of a valid identifier in JavaScript.
So what works in Firefox: "Job Directory 9463460", does not work in Internet Exploder, and has to be replaced by: "Job_Directory_9463460" for example (no spaces, no minus signs, no dots, it has to be a valid identifier).
the problem might be the wname, try using one of those shown in the link above, i quote:
Optional. String that specifies the
name of the window. This name is used
as the value for the TARGET attribute
on a form or an anchor element.
_blank The sURL is loaded into a new, unnamed window.
_media The url is loaded in the Media Bar in Microsoft Internet
Explorer 6. Microsoft Windows XP
Service Pack 2 (SP2) and later.
This feature is no longer
supported. By default the url is
loaded into a new browser window or
tab.
_parent The sURL is loaded into the current frame's parent. If the frame has no parent, this value acts as the value _self.
_search Disabled in Windows Internet Explorer 7, see Security and Compatibility in Internet Explorer 7 for details. Otherwise, the sURL is opened in the browser's search pane in Internet Explorer 5 or later.
_self The current document is replaced with the specified sURL.
_top sURL replaces any framesets that may be loaded. If there are no framesets defined, this value acts as the value _self.
if using another wname, window.open won't execute...
Actually a name can be used however it cannot have spaces so
window.open("../myPage","MyWindows",...) should work with no problem (window.open).
I also meet this issue while I used the following code:
window.open('test.html','Window title','width=1200,height=800,scrollbars=yes');
but when I delete the blank space of the "Window title" the below code is working:
window.open('test.html','Windowtitle','width=1200,height=800,scrollbars=yes');
Hi using the following code its working...
onclick="window.open('privacy_policy.php','','width=1200,height=800,scrollbars=yes');
Previously i Entered like
onclick="window.open('privacy_policy.php','Window title','width=1200,height=800,scrollbars=yes');
Means Microsoft does not allow you to enter window name it should be blank in window.open function...
Thanks,
Nilesh Pangul
For me the issue was with a dash "-" in the window name field. I removed the dashes and IE does not error out and in fact opens the window.
What does position four represent, the one that has 'false' as an value? Shouldn't that be false, (i.e. without quotes?). It's possible that earlier versions of IE would coerce the string to a boolean, but newer ones don't.
The answers here are correct in that IE does not support spaces when setting the title in window.open(), none seem to offer a workaround.
I removed the title from my window.open call (you can use null or ''), and hten added the following to the page being opened:
<script>document.title = 'My new title';</script>
Not ideal by any means, but this will allow you to set the title to whatever you want in all browsers.
Try remove the last argument. Other than that, make sure urlstring, wname, and wfeatures exist.
I discovered the same problem and after reading the first answer that supposed the problem is caused by the window name, changed it : first to '_blank', which worked fine (both compatibility and regular view), then to the previous value, only minus the space in the value :) - also worked. IMO, the problem (or part of it) is caused by IE being unable to use a normal string value as the wname. Hope this helps if anybody runs into the same problem.
If you want use the name of new window etc posting a form to this window, then the solution, that working in IE, FF, Chrome:
var ret = window.open("", "_blank");
ret.name = "NewFormName";
var myForm = document.createElement("form");
myForm.method="post";
myForm.action = "xyz.php";
myForm.target = "NewFormName";
...
It seems when even using a "valid" custom window name (not _blank, etc.) using window.open to launch a new window, there is still issues. It works fine the first time you click the link, but if you click it again (with the first launched window still up) you receive an "Error: No such interface supported" script debug.

Categories