I'm using almost same code which has been used in http://techanjs.org/. I was trying to add zooming feature in the chart as the developer has rendered the chart in here. But somehow I'm not able to zoom it. I'm getting error selection is not defined in console. I'm using following code to render the chart. https://paste.fedoraproject.org/paste/7gJq9wKL4h4s862EDuxnQQ. I'm sure I'm doing something wrong in here, I would really appreciate if I get any assistance regarding it as I'm still learning D3.
I'd guess the problem is that you are referencing the variable selection but it isn't defined.
Hence -
selection is not defined
selection is the parameter passed into your bigchart function.
But you then use it in your reset, zoomed functions where it is not defined.
//Zoom Begins
function reset() {
zoom.scale(1);
zoom.translate([0,0]);
selection.call(draw); // this will throw an error
}
function zoomed() {
x.zoomable().domain(d3.event.transform.rescaleX(zoomableInit).domain());
y.domain(d3.event.transform.rescaleY(yInit).domain());
yPercent.domain(d3.event.transform.rescaleY(yPercentInit).domain());
selection.call(draw); // this will throw an error
}
//Zoom Ends
To fix, either pass the selection to the functions as a parameter (like the other functions) - or else make the selection a property of BigChart so that it can be referenced by the reset and zoomedfunctions.
i.e.
// pass selection to the functions as a parameter
function reset(selection) {
zoom.scale(1);
zoom.translate([0,0]);
selection.call(draw);
}
function zoomed(selection) {
x.zoomable().domain(d3.event.transform.rescaleX(zoomableInit).domain());
y.domain(d3.event.transform.rescaleY(yInit).domain());
yPercent.domain(d3.event.transform.rescaleY(yPercentInit).domain());
selection.call(draw);
}
Then when you call the functions obviously you pass in the correct object...e.g.
zoom = selection.call(d3.zoom().on("zoom", zoomed));
rather than
zoom = d3.zoom().on("zoom", zoomed),
Related
I am trying to change the colour of my ngx bar chart by calling a function at [customColor] property but it is going into loop even though by animation mode is off.
I had referred to the following StackOverflow answer and even on a comment section, someone is facing the same issue.
How to use Ngx-Charts customColor function
setTimeOut Handler error
I had console the text msg 'custom colours called' inside CustomColor() function.
(which I called at [customColor]=CustomColor())
apart from it, it's working absolutely fine but not sure why it is going into loop ??
Because of the same, my system get down after a couple of minutes
console msg
would really appreciate any help.
We should avoid binding function to the property, as it gets trigger every time whenever change detection happens.
I would recommend fetching custom colors to a public array in ngOnit and bind this array to [customColor] property.
customColors: any[] = [];
constructor() {}
ngOnInit() {
this.customColors = this.getCustomColors();
}
getCustomColors() {
//retrun customColor;
}
// In template
<ngx-charts-bar-vertical
[animations]="barAnimations"
[customColors]="customColors"
...
</ngx-charts-bar-vertical>
I am try to use clastering in my aplication but I am get a error addLayer is not defined".
I have no Idea how to resolve this issue.
I just copy and paste this sample function from Here API samples api clusters
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, but the addLayer is undefined.
function startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
var dataPoints = data.map(function(item) {
return new H.clustering.DataPoint(item.latitude, item.longitude);
});
// Create a clustering provider with custom options for clusterizing the input
var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 32,
// minimum weight of points required to form a cluster
minWeight: 2
}
});
// Create a layer tha will consume objects from our clustering provider
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, bust does not exist addLayer.
I'm embed the script
<script type="text/javascript" src="https://js.api.here.com/v3/3.0/mapsjs-clustering.js"></script>
on my index.
I don't know how to resolve this issue.
If someone knows how to resolve I'm glad to listen
EDIT: Additional code per comment request:
function addMarkerToCameraGroup(map, coordinate, html) { // add and remove markers
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
}
You asked this question a second time as: "Try to create a cluster unsing a sample but addLayer got undefinied" which doesn't include some of the details in this question. Given the additional edit / context you made on this question however, it would seem you are adding an event listener in which map is probably out of scope or not yet defined for visibility inside the anonymous function.
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
You could do a typing check to see if map has been defined when the click event occurs and/or confirm whether it is an H.map. Without seeing the full listing, it may also be the case that you have not made map a global variable but instead declared it somewhere else in the page initialization so is out of scope when the click event is fired.
You can check JavaScript callback scope for details on closures where you could provide the map to the event when declaring the function. For more general information: JavaScript HTML DOM EventListener
I need to include the download icon inside the tooltip message, I have tried the below code:
ObjectIconView: Ember.ContainerView.extend(childMOMixin, {
iconDownload: function () {
model: 'download'
},
mouseEnter: function(e) {
if(type == 'Text'){
var textUrl = {content: 'Preview is Not Available, Use '+ this.iconDownload() +'Menu'};
this.$().tooltip(textUrl);
}
}
In that I have called the iconDownload inside the tooltip. But it's saying undefined in the output. I'm using Ember 1.4.0 version. Can anybody please provide the suggestion for this. I'm new to the Ember. Thanks in advance
There are two things that you need to change to get the tooltip to display the data you're expecting.
1: Return something from iconDownload
Right now, the function returns nothing, it makes an internal list and then does nothing.
Does it even need to be a function, or could it just be a string, object?
2: You're not accessing the data in it correctly.
Assuming you're actually needing a hash returned, you're not accessing the data properly - all you're doing is getting the object.
With the structure you have right now, you'r string generator would be
'Preview is Not Available, Use '+ this.iconDownload().model +'Menu'
I'd recommend a couple of additional changes, if they're possible.
1: Use the Ember getter to get data from iconDownload.
Instead of this.iconDownload, call this.get('iconDownload.model') or this.get('iconDownload')
2: Make the actual tooltip text a computed property.
toolTipText: function () {
return `Preview is Not Available, Use ${this.get('iconDownload.model')} Menu`;
}.property('iconDownload.model');
Now, you can just call this.get('toolTipText') to get what the tooltip says.
3: Move your mouseEnter function into the actions section of your view's javascript
I am extending mxgraph delete control example to add delete like controls to nodes which are generated dynamically in my graph. The source code for the example is available here
The problem is in this part of the code -
// Overridden to add an additional control to the state at creation time
mxCellRendererCreateControl = mxCellRenderer.prototype.createControl;
mxCellRenderer.prototype.createControl = function(state)
{
mxCellRendererCreateControl.apply(this, arguments);
var graph = state.view.graph;
if (graph.getModel().isVertex(state.cell))
{
if (state.deleteControl == null)
mxCellRendererCreateControl.apply inside the overridden call back of createControl seems to work as intended (calls the original function before creating additional controls) with the initial state of the graph on load. But, once I add nodes dynamically to the graph and the callback is invoked by mxgraph's validate/redraw, the control goes into an infinite loop, where 'apply' function basically keeps calling itself (i.e, the callback).
I am a bit clueless because when I debug, the context(this) looks fine, but I can't figure out why instead of invoking the prototype method, it just keeps invoking the overridden function in a loop. What am I doing wrong?
It looks like you are not cloning your original function the right way, please try the following :
Function.prototype.clone = function() {
var that = this;
return function theClone() {
return that.apply(this, arguments);
};
};
Add that new method somewhere in your main code so it will available in the whole application, now you can change your code to :
// Overridden to add an additional control to the state at creation time
let mxCellRendererCreateControl = mxCellRenderer.prototype.createControl.clone();
mxCellRenderer.prototype.createControl = function(state) {
mxCellRendererCreateControl(state);
var graph = state.view.graph;
if (graph.getModel().isVertex(state.cell)) {
if (state.deleteControl == null) {
// ...
}
}
// ...
};
This should work if I understood your problem correctly, if it does not, please change the old function call back to the apply. Otherwise let me know if something different happened after the Function prototype change.
It seems that your overriding code is being called multiple times (adding a simple console.log before your overriding code should be enough to test this)
Try to ensure that the code that overrides the function only gets called once, or validate whether the prototype function is the original or yours.
Here is an example of how you can check if the function is yours or not
if (!mxCellRenderer.prototype.createControl.isOverridenByMe) {
let mxCellRendererCreateControl = mxCellRenderer.prototype.createControl;
mxCellRenderer.prototype.createControl = function(state) { /* ... */ };
mxCellRenderer.prototype.createControl.isOverridenByMe = true;
}
There are other ways, like using a global variable to check if you have overriden the method or not.
If this doesn't fix your issue, please post more about the rest of your code (how is this code being loaded/called would help a lot)
I thought I'd finally figured out JavaScript callbacks as I found a use for one, but it is firing out of sequence.
In a Google Maps application I have a function which checks if the map is zoomed to the maximum level before allowing the user to store the (new) location of a marker.
The check function is:
function checkForMaxAccuracy(nextOperation) {
// Check at full zoom and alert if not
maxZoomService.getMaxZoomAtLatLng( newLocationMarker.getPosition(), function(response) {
var levelToZoomTo;
if (response.status != google.maps.MaxZoomStatus.OK) {
alert("Please ensure you are at maximum zoom to ensure most accurate placement possible.");
// continue after this alert as Mao could be fully zoomed but zoom service not reporting correctly
} else {
//alert("The maximum zoom at this location is: " + response.zoom);
if (response.zoom > map.getZoom()) {
alert("You must be zoomed in to the maximum to ensure most accurate placement possible before saving.\n\n Click [ Zoom here ] in theInfo Window to zoom to the maximum.");
// return after this error as Mao is definitely not fully zoomed
return;
}
// Call the update function to do the saving to the database
nextOperation();
}
});
}
Where nextOperation is the callback function.
This is called by two different functions, the first, and simplest (because it's not fully written yet) works perfectly:
function saveNewLocation() {
checkForMaxAccuracy(function () {
alert("save new");
});
}
If not fully zoomed I get the warning message displayed by the check function. If the map IS fully zoomed I get the alert 'save new' message displayed which is a place holder for the code to do the database update.
However, the same check function is also called from a more complete function. This other function is called when the user is updating the location of an existing marker.
This second function actually sets the onclick property of an HTML span object - effectively enabling and disabling the save control depending on what is going on.
In this function I am setting the onclick as follows:
document.getElementById('savePosition'+locationId).onclick = (state)?function(){checkForMaxAccuracy(doUpdate(locationId,"position"));}:null;
In this case, when I click the corresponding span element the doUpdate() function gets fired before the checkForMaxAccuracy() function.
(Apologies for the use of ternary operator.. I know if makes things a little difficult to read, but I'm leaving as is in my code in case I've got the bracketing or syntax slightly wrong here and that's what's causing my problems.)
My guess is I'm getting something fundamentally wrong in my 'understanding' of callback functions.
Can anyone explain what I'm doing wrong?
-FM
checkForMaxAccuracy(
doUpdate(locationId,"position")
);
will pass the returned value of doUpdate as an argument of checkForMaxAccuracy. In other words, you're not passing the callback function itself but its return value.
What you could do is:
checkForMaxAccuracy(
function() {
doUpdate(locationId,"position")
}
);