Why is this tree layout giving me an infinite loop? - javascript

I am new to d3 and trying to do a simple tree layout over some xml data. I am getting an infinite loop in some d3 code and trying to find out why. Here is a simplification of what I am doing and I am still seeing the infinite loop.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring Integration Inspector</title>
<script src="js/d3.js"></script>
<script type="text/javascript">
var parser = new DOMParser();
var xml = parser.parseFromString("<beans><bean/><bean><beanChild/></bean></beans>", "text/xml");
var tree = d3.layout.tree().children(function(beanNode) {
var children = beanNode.getElementsByTagName("*");
if (children.length > 0) {
return children;
} else {
return null;
}
});
var nodes = tree.nodes(xml),
links = tree.links(nodes);
</script>
</head>
<body>
<div id="graph"></div>
</body>
</html>
To reproduce, copy this code into an index.html file and include the d3.js library appropriately. This will not load in a browser. I think it has something to do with the children function.
EDIT:
I am stepping through the debugger in chrome and the problem is located inside of the apportion method. The while loop never breaks. More specifically, the d3_layout_treeRight and d3_layout_treeLeft methods (which I think tries to find the first child and last child respectively) are simply returning the current node when the current node is a leaf.
The value of node._tree.thread is the current node inside of d3_layout_treeRight and d3_layout_treeLeft. and so calls to those methods return the node passed in as an argument.

As described on the d3-js google group, the problem is that I used beanNode.getElementsByTagName("*") instead of beansNode.childNodes.

Related

How do I call the JavaScript function properly?

<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Example</title>
<script>
function displayString() {
return "<h1>Main Heading</h1>"
}
displayString();
document.write("Execute during page load from the head<br>");
</script>
</head>
<body>
<script>
document.write("Execute during page load from the body<br>");
</script>
</body>
</html>
So this is my problem. No matter where I put the displayString(), the h1 just never seems to show up on the browser. Can anybody please help me see where I am wrong? I am new to JavaScript. Oh, and what I am trying to do is to call the function.
You need to write the returned String to the document:
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Example</title>
<script>
function displayString() {
return "<h1>Main Heading</h1>"
}
document.write(displayString());
document.write("Execute during page load from the head<br>");
</script>
</head>
<body>
<script>
document.write("Execute during page load from the body<br>");
</script>
</body>
</html>
No matter where I put the displayString(), the h1 just never seems to
show up on the browser.
If you wish to add a new element to a document, several approaches are available:
document.write (effectively deprecated)
.innerHTML (sometimes useful, but can be slow)
DOM API - recommended approach
The recommended approach is to use the DOM API.
DOM stands for Document Object Model. Essentially it's the markup of your document represented as a tree-like structure of nodes. There are many DOM API functions which allow you to:
add
remove
append
prepend
insert
update
new DOM nodes.
Any DOM node may be added, removed or updated, including:
parent elements
child elements
sibling elements
element attributes
ids, classNames, classLists
custom data-* attributes
text nodes
Here is an example:
function displayMainHeading () {
let mainHeading = document.createElement('h1');
mainHeading.textContent = 'Main Heading';
document.body.prepend(mainHeading);
}
displayMainHeading();
<p>Paragraph 1</p>
<p>Paragraph 2</p>
Further Reading
This is a good primer to get you started:
A Beginners Guide To DOM Manipulation by Iqra Masroor

JS - Cloning part of an external webpage

I'm trying to include a table from a webpage in a different domain.
I went for the easiest path using a proxy to fulfill my request and embedded the page directly into an iFrame.
Everything works fine but I'm still missing my initial (and final) objective: clone exactly (and only) one portion of the page, not the whole thing.
This is the simple snippet:
function loadIframe() {
var _body = document.getElementsByTagName('body')[0];
var _div = document.createElement('iframe');
_div.src = "http://cors.io/?https://eshop-prices.com/?currency=EUR";
_div.id = "iFrame";
_div.width = "100%";
_div.height = "1080";
_body.appendChild(_div);
}
loadIframe();
<!DOCTYPE html>
<head lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>eShop Prices</title>
</head>
<body>
<script type="application/javascript" src="js/util.js"></script>
</body>
</html>
Run this outside of stackoverflow or you'll see an empty iframe.

All Javascript line not executed

I have a simple html page is as-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(e) {
var s = $("#d").get(0).getElementsByTagName("a");
for(var x=0;x<s.length;x++){
document.writeln(s.length);
}
var k=document.createElement("a");
k.innerHTML="hello";
var q=document.getElementById("d");
q.appendChild(k);
});
</script>
</head>
<body>
<div id="d">
<a><img class="zzz"/></a>
<a><img class="zzz"/></a>
</div>
</body>
</html>
Javascript executes only up to for loop (element k is not appended). If for loop is removed then only element k got appended. Isn't code below for loop is supposed to be executed after for loop execution?
Welcome to StackOverflow! A few suggestions to help you as you are learning to develop:
Always use meaningful variable names, it's hard to keep track of what
single letter variables represent
Don't use document.write for
debugging, use the console for that
If you are using a library like
jQuery, try to use it as much as you can when you are beginning to
learn it. Only fall back to basic javascript if you have a compelling
reason to do so
Your function can be rewritten in pure jQuery like so:
$(function() {
var container = $('#d');
console.log(container.find('a').length);
container.append('<a>hello</a>');
});
I haven't run your code, but your error probably has to do with this statement: $("#d").get(0).getElementsByTagName("a");. The eq() method returns a jQuery object, which does not have a getElementsByTagName() method on it.
If you want a plain DOM object without the jQuery wrapper you can address the jQuery object like an array: $('#d')[0].getElementsByTagName("a");, though like I said, it's best to stick with the jQuery library if you are going to use it.
Good luck as you learn!
you can't use writeln (or write) after the document has been loaded(or I better say: you shouldn't, because it will overwrite the complete document, including #d , what will force the error, because this element isn't available anymore after the usage of writeln )
I guess you want something like this:
$(document).ready(function(e) {
$('a').prepend(function(i){return i;});
$('#d').append('hello');
});
Demo: http://jsfiddle.net/stRBU/2/

Why isn't this javascript node traversal working?

I'm primarily a C#, Java, PHP Developer; associated databases encapsulated. Seemingly irrelevant, but a valid precursor to the statement that I feel like I'm 15 again; glaring at this... disappointingly simple javascript, that doesn't seem to be turning up anything for me.
My intention here is to loop through the nodes in my current document, evaluate their attributes, and perform actions on particular nodes. My code is as follows ( again... so simple I feel like a dunce ), but the output is rather inconsistent.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
function TraverseDocument()
{
var Root = document.documentElement;
for( Element in Root.childNodes )
{
document.writeln(Element);
}
}
</script>
</head>
<body onLoad="javascript: TraverseDocument();">
<div id="test" testAttr="testData">
</div>
</body>
</html>
Now; consider that this is just my fifth pass at this ( tutorials, examples, etc ), and I've tried a few permutations on this code:
// document.writeln(Element.nodeType);
// document.writeln(Element.nodeName);
// document.writeln(Element.nodeValue);
All of which come up short; displaying 'undefined'. The current code ( as shown in my first code block ) outputs the following:
0 1 2 length item
Can anyone point me at where I'm going wrong here? Rookie question; but one that I still can't manage to put my finger on. Thanks ahead of time.
Simple enough, the for loop you've written iterates the properties of the object, rather than the items in the array, what you probably want is actually:
function TraverseDocument()
{
var Root = document.documentElement;
for(var i = 0; i < Root.childNodes.length; i++ )
{
document.writeln(Root.childNodes[i]);
}
}

Adding divs to the HTML body using Lift

I have been playing around with Scala/Lift/Comet/Ajax etc. recently. I came across a problem which boils down to this:
Summary
I want to update a specific div (by id) when a certain event occurs. If the div does not exist yet, it must be created and appended to the HTML body.
Currently I cannot get this to work when using the Lift framework.
Source File
LIFT_PROJECT/src/main/webapp/static/mouseViewTest.html:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
// <![CDATA[
$(document).ready(function() {
updateOrCreateMouseDiv('123', 'coords')
});
function updateOrCreateMouseDiv(uniqueId, coords) {
if ($('#mouse_'+uniqueId).length == 0) {
$('body').append('<div id=' + uniqueId + '>' + coords + '</div>');
}
$('#mouse_'+uniqueId).html(coords)
}
// ]]>
</script>
</head>
<body></body>
</html>
The Error
If I open the above file directly in a browser (file:///LIFT_PROJECT/src/main/webapp/static/mouseViewTest.html) it works i.e. a new div is created.
But if I run it through Lift/Jetty (http://localhost:8080/static/mouseViewTest) I get the following JavaScript error:
Chrome:
Uncaught Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7
Firefox (Firebug):
An invalid or illegal string was specified" code: "12
Comparing the Sources in Browser
When comparing the page sources in the browser, I can see only one difference, namely: Lift adds the following JavaScript just before the closing </body> tag:
<script type="text/javascript" src="/ajax_request/liftAjax.js"></script>
<script type="text/javascript">
// <![CDATA[
var lift_page = "F320717045475W3A";
// ]]>
</script>
Questions
Does anyone have an idea why this happens?
If I would want to move the JavaScript code into the Scala file (using Lift's JavaScript and jQuery support), what would the code look like?
Please note: When I used Jq("body") ~> JqAppend() to create new divs, it worked. I just didn't know how to check whether the div id already existed. Thats why I moved the code into the template, planning on using Lift's Call function to execute the JS function. And thats when these problems started...
Thanks!
I recently ran into a similar problem and, from what I've gathered, the problem is because the page when served by lift is served as XHTML and there are some issues when writing to the DOM if the page is XHTML vs. HTML. I don't know whether this is a bug with jQuery or Safari or if it's just something that's not possible in XHTML, but a quick way to fix it is to modify your Boot.scala to tell Lift to not use XHTML as the mime type with this line:
LiftRules.useXhtmlMimeType = false

Categories

Resources