d3.js failed to update data binding - d3.js

Absolutely newbie to d3.js
I am trying out a tutorial pull off from internet which should be straight-foward but I am pulling my hair off now
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://d3js.org/d3.v6.min.js"></script>
</head>
<style>
body {font-family: Arial;}
</style>
<body>
<ul id="list">
<li></li>
<li></li>
</ul>
<input type="button" name="load" value="Load List" onclick="javascript:load()"/>
<input type="button" name="remove" value="Remove Fourth Value" onclick="javascript:remove()"/>
<script>
function load() {
d3.select("#list").selectAll("li")
.data([10,20,30,25,15])
.text(function(d){console.log(d); return "This is pre-existing element and the value is " + d;})
.enter()
.append("li")
.text(function(d){return "This is dynamically created element and the value is "+d;})
}
function remove() {
d3.select("#list").selectAll("li")
.data([10,30,25,15])
.exit()
.remove()
}
</script>
</body>
</html>
The HTML page will loaded with two empty pre-defined bullet points. The list will build after you click the "Load" button which is all fine. The logic I don't quite understand is on the "remove()" function which, by providing a new version of data, shouldn't d3.js remove the 2nd item on the list? Instead, it always remove the last item on the list as if the update is based on the size of the array passed to .data() instead of the actual values
In fact the original tutorial is not working as it described. But .exit() and .remove() should be comparing the existing data with the given new data and remove the one that is missed out in the new data?
Appreciate any help here. Thanks in advance!

Related

when setting content field to a div element.. having issues with attaching and visibility

Problem:I am assigning a div to the content property of a kendo tooltip... problem is, when I attached the tooltip... the div is sitting there, and the tooltip does not REALLY wire up until I hover over the element I attached it to... you can see in my code below how this is not working... paste into a kendo dojo, and seee.... just click the button (DO NOT HOVER over the text box yet).. then you will see the div show up, and when you hover over the text box, it will do what it's supposed to do... I made a workaround , which is commented out... but it flashes for a second... is there a way to just make the tooltip wire up and hide the content div?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.223/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.223/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.223/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.223/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2017.1.223/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2017.1.223/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2017.1.223/js/kendo.all.min.js"></script>
</head>
<body>
<div id="view" data-bind="enabled: isNameEnabled">
<button id="button1" data-bind="click: updateTooltip">Change Tooltip</button>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<input id="text1" type="text" data-bind="value: name" />
<div id="toolTipDiv"></div>
</div>
<script>
var viewModel = kendo.observable({
isNameEnabled: false,
name: "John Doe",
updateTooltip: function () {
var kendoToolTip = window.toolTipEl.data("kendoTooltip");
// comment this out to see
//div1.hide();
//kendoToolTip.show();
//kendoToolTip.hide();
//div1.show();
//end comment
div1.text(text1.value);
}
});
var div1 = $("#toolTipDiv");
window.toolTipEl = $("#text1");
kendo.bind($("#view"), viewModel);
window.toolTipEl.kendoTooltip({
content: div1, position: "top",autohide:true
});
</script></body>
</html>
The div shows up because it is visible and you just made its contents non-blank. Once the tooltip is shown once, kendo takes over control and wraps it in another div that it hides and shows as necessary.
Note that "aria-hidden: true" does not actually hide the div...it is simply a directive to screen-readers...you still have to actually use real CSS to hide the div.
You need to ensure that the div is hidden initially(before kendo wraps it) and remove the display: none; once you "hand it off" to kendo.
Or...hide the div and set the content to a function that just returns the content of the div instead of binding to the div itself, i.e.
<div id="toolTipDiv" aria-hidden="true" style="display: none"></div>
...
updateTooltip: function () {
div1.text(text1.value);
}
...
window.toolTipEl.kendoTooltip({
content: function(e) {
return div1.text();
},
Example: http://dojo.telerik.com/#Stephen/iqaLA
Update
Turns out that the content only gets called the first time the tip is shown for the element, not every time the tooltip is shown, so dynamic changes to the contents (or even the input's title attribute) don't change the tooltip.
So, ignore my answer and try this: http://www.telerik.com/forums/dynamic-content-de3951ae5752

angular-ui bootstrap typeahead limit is not working

I am new to angularjs. From this web site https://angular-ui.github.io/bootstrap/ I got typeahead directive for my angularjs project but my limit and filter are not working here is my code.
When I type "c" in the text field I want only 8 records to be displayed but instead all records are displayed.
plunker
http://plnkr.co/edit/RhwHmKwSxWBh3rp0u85O?p=preview
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl', function($scope, $http) {
$scope.getLocation = function(val) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(response){
return response.data.results.map(function(item){
return item.formatted_address;
});
});
};
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<script type="text/ng-template" id="customTemplate.html">
<a>
<img ng-src="http://upload.wikimedia.org/wikipedia/commons/thumb/{{match.model.flag}}" width="16">
<span bind-html-unsafe="match.label | typeaheadHighlight:query"></span>
</a>
</script>
<div class='container-fluid' ng-controller="TypeaheadCtrl">
<h4>Asynchronous results</h4>
<pre>Model: {{asyncSelected | json}}</pre>
<input type="text" ng-model="asyncSelected" placeholder="Locations loaded via $http" typeahead="address for address in getLocation($viewValue) | filter:$viewValue |limitTo:8" typeahead-loading="loadingLocations" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
</div>
</body>
</html>
I know this is an old question, but I'll go ahead and answer it anyway for future reference:
This is a known behaviour when loading via $http as the limit would apply to the promise when calling your get method, which would result in it not applying to the actual result set by the time your promise resolves.
See issue #1740 in ui.bootstrap repository for more information on this.
The work around for this is either rolling your own filter function and return a promise from that filter instead of fetching the records directly or implement a limit parameter in the API and limit it server side.

D3 example not working

I just copy pasted this from the first example in here:
http://www.recursion.org/d3-for-mere-mortals/
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<!--<script src="d3/d3.v3.js"></script>-->
<script src="/d3/d3.v3.js"></script>
<div>
<script>
var rectDemo = d3.select("#rect-demo").
append("svg:svg").
attr("width", 400).
attr("height", 300);
rectDemo.append("svg:rect").
attr("x", 100).
attr("y", 100).
attr("height", 100).
attr("width", 200);
d3.selectAll("body").append(rectDemo) ;
</script>
</div>
</body>
and it shows nothing on the page. I am sure I am doing something stupid here but this is my first example and can't figure out what is going it....
The script attempts to draw the rectangle in a svg element that's added inside the (already existing) element with id="rect-demo".
Therefore, you need to have an HTML element (for example a <div>) with the appropriate id:
<div id="rect-demo"> </div>
See this live demo: http://jsbin.com/enisen/2/edit

Add image to page onclick

I want a button to add an image to the current page on each click. For example, the first time you open the page, there is one picture. Then you click the button and the same picture appears on the page and now you have two same pictures. Then you keep on pressing on the button and more and more same pictures appear. This is the code I tried that didn't work:
<script type="text/javascript">
function addimage() {<img src="http://bricksplayground.webs.com/brick.PNG" height="50" width="100">}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>
</html>
Please help! Thanks.
You should probably know that javascript can create html elements, but you cannot directly embed html inside javascript (they are two completely separate things with different grammars and keywords). So it's not valid to have a function that only contains html -- you need to create the elements you want, and then append them to the dom elements that you want them to. In this case, you create a new image and then append it to the body.
<html>
<body>
<script type="text/javascript">
function addimage() {
var img = document.createElement("img");
img.src = "http://bricksplayground.webs.com/brick.PNG";
img.height = 50;
img.width = 100;
//optionally set a css class on the image
var class_name = "foo";
img.setAttribute("class", class_name);
document.body.appendChild(img);
}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>
</html>
All you're missing is a method to write the element on the page
<script type="text/javascript">
function addimage() {
document.write('<img src="http://bricksplayground.webs.com/brick.PNG" height="50" width="100">')
}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>

Loading new content into <body> and keeping input fields value from previous <body> state?

I'm trying to make my own tumblr search (tags only) since their own search function doesn't actually work.
So I'm nearly there. It works, but I need the search field to keep the value of what the user searched for.
So if I search for "foobar", it loads the tumblr.com/tagged/foobar directly into my tumblr.com, but the search field still contains the term "foobar"
Here is my working code except for the code where I'm trying to insert the previous search term into the newly loaded
Thanks in advance.
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
jQuery(function($) {
$('#syndex').keydown(function(event) {
if (event.keyCode == '13') {
var syndex = $('input:text').val();
$('body').load("http://syndex.me/tagged/"+ syndex);
$(this).val(syndex); //this is what's not working
}
});
});
</script>
</head>
<body>
<div id="logo">
<input id="syndex" type="text"/>
</div>
</body>
</html>
You need to put this into the complete function which can be passed as a parameter to load.
http://api.jquery.com/load/
Load makes an AJAX call which is asynchronous. You are trying to set the value prior to the content being loaded.
$('body').load("http://syndex.me/tagged/"+ syndex,function(){
$('input:text').val(syndex);
});

Resources