I've built a force chart application.
http://jsfiddle.net/NYEaX/130/
I want to be able to define different shapes and maybe even change the fill backgrounds for specific user images. I'm aware of the def pattern method - is this best way to go about it. How do I create the function to control the shape of the node?
var circle = svg.append("svg:g")
.attr("class", "circle")
.selectAll("circle")
.data(force.nodes())
.enter()
.append("svg:circle")
.attr("class", function(d) {
return "level"+d.level;
})
.attr("r", function(d) {
if(d.level > 0){
return getRadius(d);
}
else{
return "0";
}
})
.style("fill", function(d) {
return color(d.group);
})
Here is the latest example - I've pushed the transform attributes on the exit to have the shapes fly to the left and up - keen to enhance/clean up the code - any help from anyone to make it more efficient?
**LATEST CODE -- http://jsfiddle.net/NYEaX/617/ **
var users = that.vis.selectAll("path")
.data(that.nodes);
// Enter
users
.enter().append("path")
.attr("id", function(d){
return d.id;
})
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("d", d3.svg.symbol()
.size(function(d) { return d.size; })
.type(function(d) { return d.type; }))
.style("fill", "steelblue")
.style("stroke", "white")
.style("stroke-width", "1.5px")
.call(that.force.drag);
// Update
users
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.transition()
.duration(500);
// Exit
users.exit()
.transition()
.duration(750)
.attr("transform", function(d) { return "translate(-100,100)"; })
.remove();
I've modified the example to start to mimic an "online now" application. I want to represent users via the symbols and have the symbols gravitate towards the center - much like the example.
http://jsfiddle.net/NYEaX/231/
I've toggled the data and managed to update the force chart - but its snapping instead of fading in and out the symbols and there is no gravitation - on start up or on update.
this is the current plot code
//__morph plots
var plots = this.vis.selectAll("path")
.data(this.nodes)
// Enter
plots.enter()
.append("svg:path")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("d", d3.svg.symbol()
.size(function(d) { return d.size; })
.type(function(d) { return d.type; }))
.style("fill", "steelblue")
.style("stroke", "white")
.style("stroke-width", "1.5px")
.call(this.force.drag);
// Update
plots
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.transition()
.duration(500)
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
// Exit
plots.exit()
.transition()
.duration(250)
.remove();
//__morph plots
Related
I am building a d3 function to build a grouped bar chart that can transition into a stacked bar chart. Everything was working fine until I tried to bring in date values for the x-axis. Now the chart only graphs one bar. The X axis shows correctly but the position of the rectangles seems to be off. My jsFiddle is posted at the bottom of the code.
function createChart(inputdata,chartname,inputtop,inputbottom,inputwidth,inputheight){
var stack = d3.layout.stack(),
layers = inputdata,
m = layers[0].length, // number of samples per layer
n = layers.length, // number of layers
data = stack(d3.range(n).map(function(d) { return layers[d]; }));
var yGroupMax = d3.max(data, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(data, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var margin = {top: inputtop, right: 10, bottom: inputbottom, left: 10},
width = inputwidth - margin.left - margin.right,
height = inputheight - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([0, width], .08);
var xTime = d3.time.scale()
.domain([new Date("2016-01-01"), d3.time.day.offset(new Date("2016-01-04"), 1)])
.rangeRound([0, width - margin.left - margin.right]);
var xAxisTime = d3.svg.axis()
.scale(xTime)
.orient('bottom')
.ticks(d3.time.days, 1)
.tickFormat(d3.time.format('%a %d'))
.tickSize(0)
.tickPadding(8);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(2)
.tickPadding(6)
.outerTickSize(0);
var svg = d3.select(chartname).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(data)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0);
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisTime)
svg.append("g")
.attr("class", "yaxis")
.attr("transform", "translate(" + (Number(margin.left) + 14) + ",0)")
.call(yAxis);
svg.select("g.yaxis").selectAll(".tick")
.each(function (d) {
if ( d === 0 ) {
this.remove();
}
});
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
d3.select("input[value=\"0\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
if (this.value === "grouped") transitionGrouped();
if (this.value === "stacked") transitionStacked();
//else transitionStacked();
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
var allchart = d3.selectAll(".chart").selectAll(".layer").selectAll("rect"),
axistran = d3.selectAll(".chart");
allchart.transition()
.ease("linear")
.duration(300)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) { return x(d.x) + x.rangeBand() / n * j; })
.attr("width", x.rangeBand() / n)
.transition()
.duration(200)
.ease("linear")
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); });
axistran.select("g.yaxis").transition()
.duration(600)
.call(yAxis);
axistran.select("g.yaxis").selectAll(".tick")
.each(function (d) {
if ( d === 0 ) {
this.remove();
}
});
};
function transitionStacked() {
y.domain([0, yStackMax]);
var allchart = d3.selectAll(".chart").selectAll(".layer").selectAll("rect"),
axistran = d3.selectAll(".chart");
allchart.transition()
.ease("linear")
.duration(300)
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.duration(200)
.ease("linear")
.attr("x", function(d) { return x(d.x); })
.attr("width", x.rangeBand());
axistran.select("g.yaxis").transition()
.duration(600)
.call(yAxis);
axistran.select("g.yaxis").selectAll(".tick")
.each(function (d) {
if ( d === 0 ) {
this.remove();
}
});
};
};
JSFiddle Link
You've created a time scale in variable xTime, but you aren't using it to draw the rects:
var rect = layer.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.attr("x", function(d) {
return xTime(new Date(d.x)); //<-- don't use x here
});
Also, If you are using a time axis, I recommend changing your input data into datetimes instead of new Date( everywhere.
Finally, your selections are wrong in your transitions.
Here it is all fixed up:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 700px;
}
text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
</style>
</head>
<body>
<form>
<label>
<input type="radio" name="mode" value="grouped" /> Grouped
</label>
<label>
<input type="radio" name="mode" value="stacked" checked="" /> Stacked
</label>
</form>
<chart_1></chart_1>
<script>
var layers = [{
"x": "2016-01-01",
"y": 4,
"z": 5
}, {
"x": "2016-01-02",
"y": 5,
"z": 6
}, {
"x": "2016-01-03",
"y": 6,
"z": 3
}, {
"x": "2016-01-04",
"y": 7,
"z": 1
}];
var converted = convertjson(layers, "x", ["y", "z"]);
createChart(converted, "chart_1", 40, 20, 700, 550);
function createChart(inputdata, chartname, inputtop, inputbottom, inputwidth, inputheight) {
var stack = d3.layout.stack(),
layers = inputdata,
m = layers[0].length, // number of samples per layer
n = layers.length, // number of layers
data = stack(d3.range(n).map(function(d) {
return layers[d];
}));
var yGroupMax = d3.max(data, function(layer) {
return d3.max(layer, function(d) {
return d.y;
});
}),
yStackMax = d3.max(data, function(layer) {
return d3.max(layer, function(d) {
return d.y0 + d.y;
});
});
var margin = {
top: inputtop,
right: 10,
bottom: inputbottom,
left: 10
},
width = inputwidth - margin.left - margin.right,
height = inputheight - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([0, width], .08);
var xTime = d3.time.scale()
.domain([new Date("2016-01-01"), d3.time.day.offset(new Date("2016-01-04"), 1)])
.rangeRound([0, width - margin.left - margin.right]);
var xAxisTime = d3.svg.axis()
.scale(xTime)
.orient('bottom')
.ticks(d3.time.days, 1)
.tickFormat(d3.time.format('%a %d'))
.tickSize(0)
.tickPadding(8);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(2)
.tickPadding(6)
.outerTickSize(0);
var svg = d3.select(chartname).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(data)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) {
return color(i);
});
var rect = layer.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.attr("x", function(d) {
return xTime(d.x);
})
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0);
rect.transition()
.delay(function(d, i) {
return i * 10;
})
.attr("y", function(d) {
return y(d.y0 + d.y);
})
.attr("height", function(d) {
return y(d.y0) - y(d.y0 + d.y);
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisTime)
svg.append("g")
.attr("class", "yaxis")
.attr("transform", "translate(" + (Number(margin.left) + 14) + ",0)")
.call(yAxis);
svg.select("g.yaxis").selectAll(".tick")
.each(function(d) {
if (d === 0) {
this.remove();
}
});
d3.selectAll("input").on("change", change);
/*
var timeout = setTimeout(function() {
d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
d3.select("input[value=\"0\"]").property("checked", true).each(change);
}, 2000);
*/
function change() {
//clearTimeout(timeout);
if (this.value === "grouped") transitionGrouped();
if (this.value === "stacked") transitionStacked();
//else transitionStacked();
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
var allchart = d3.selectAll(".layer").selectAll("rect"),
axistran = d3.selectAll(".chart");
console.log(allchart)
allchart.transition()
.ease("linear")
.duration(300)
.delay(function(d, i) {
return i * 10;
})
.attr("x", function(d, i, j) {
return xTime(d.x) + x.rangeBand() / n * j;
})
.attr("width", x.rangeBand() / n)
.transition()
.duration(200)
.ease("linear")
.attr("y", function(d) {
return y(d.y);
})
.attr("height", function(d) {
return height - y(d.y);
});
axistran.select("g.yaxis").transition()
.duration(600)
.call(yAxis);
axistran.select("g.yaxis").selectAll(".tick")
.each(function(d) {
if (d === 0) {
this.remove();
}
});
};
function transitionStacked() {
y.domain([0, yStackMax]);
var allchart = d3.selectAll(".layer").selectAll("rect"),
axistran = d3.selectAll(".chart");
allchart.transition()
.ease("linear")
.duration(300)
.delay(function(d, i) {
return i * 10;
})
.attr("y", function(d) {
return y(d.y0 + d.y);
})
.attr("height", function(d) {
return y(d.y0) - y(d.y0 + d.y);
})
.transition()
.duration(200)
.ease("linear")
.attr("x", function(d) {
return xTime(d.x);
})
.attr("width", x.rangeBand());
axistran.select("g.yaxis").transition()
.duration(600)
.call(yAxis);
axistran.select("g.yaxis").selectAll(".tick")
.each(function(d) {
if (d === 0) {
this.remove();
}
});
};
};
function convertjson(data, xValue, yArray) {
var arrayconvertedjson = [];
var convertedjson = [];
for (var j = 0; j < yArray.length; j++) {
for (var i = 0; i < data.length; i++) {
convertedjson.push({
"x": new Date(data[i][xValue]),
"y": data[i][yArray[j]]
});
};
arrayconvertedjson.push(convertedjson)
convertedjson = [];
};
return arrayconvertedjson;
};
</script>
</body>
</html>
I know you use
editor.setValue("");
to set one value but how do you append in CodeMirror?
IE:
editor.appendText();?
Use replaceRange. For example editor.replaceRange(myString, CodeMirror.Pos(editor.lastLine())). Re-setting the entire editor is needlessly expensive.
Here is a little script I wrote to add code to any editor (in Joomla):
function addCodeToEditor(code_string, editor_id, merge, merge_target){
if (Joomla.editors.instances.hasOwnProperty(editor_id)) {
var old_code_string = Joomla.editors.instances[editor_id].getValue();
if (merge && old_code_string.length > 0) {
// make sure not to load the same string twice
if (old_code_string.indexOf(code_string) == -1) {
if ('prepend' === merge_target) {
var _string = code_string + "\n\n" + old_code_string;
} else if (merge_target && 'append' !== merge_target) {
var old_code_array = old_code_string.split(merge_target);
if (old_code_array.length > 1) {
var _string = old_code_array.shift() + "\n\n" + code_string + "\n\n" + merge_target + old_code_array.join(merge_target);
} else {
var _string = code_string + "\n\n" + merge_target + old_code_array.join('');
}
} else {
var _string = old_code_string + "\n\n" + code_string;
}
Joomla.editors.instances[editor_id].setValue(_string.trim());
return true;
}
} else {
Joomla.editors.instances[editor_id].setValue(code_string.trim());
return true;
}
} else {
var old_code_string = jQuery('textarea#'+editor_id).val();
if (merge && old_code_string.length > 0) {
// make sure not to load the same string twice
if (old_code_string.indexOf(code_string) == -1) {
if ('prepend' === merge_target) {
var _string = code_string + "\n\n" + old_code_string;
} else if (merge_target && 'append' !== merge_target) {
var old_code_array = old_code_string.split(merge_target);
if (old_code_array.length > 1) {
var _string = old_code_array.shift() + "\n\n" + code_string + "\n\n" + merge_target + old_code_array.join(merge_target);
} else {
var _string = code_string + "\n\n" + merge_target + old_code_array.join('');
}
} else {
var _string = old_code_string + "\n\n" + code_string;
}
jQuery('textarea#'+editor_id).val(_string.trim());
return true;
}
} else {
jQuery('textarea#'+editor_id).val(code_string.trim());
return true;
}
}
return false;
}
The advantage it this script is you can work with multiple editors on the page.
I wan't to do a very simple chart with mouse interaction.
Example (work in progress) is on this page : http://velo70.ouvaton.org/2013/gpxvtt-un-nouveau-plugin/
The goal is : when you change the slider position, a circle have the same position on the chart. On the map, it's already done :)
The best issue could be : when you move the slide, the circle-chart move, and when you move the circle on the chart, the slide move too... But maybe too hard for me :\
Any link with tutorial to progress with that ?
Thanks.
One way is to bind circles to every data point in your graph and then set the display: none to all but the one that corresponds to your active slider position.
Add the circles after you append path.lineSup:
chart.selectAll("circle.highlightPoint")
.data(data)
.enter()
.append("circle")
.attr("class", "highlightPoint")
.attr("fill", "pink")
.attr("cx", function(d) { return x(d.dist); })
.attr("cy", function(d) { return y(d.ele); })
.attr("display", "none");
Add to your slider function:
d3.selectAll("circle.highlightPoint")
.attr("display", function(d,i) { return i == id ? "block" : "none"});
I think that should work.
Thanks. Good and pedagogic way for me :)
I finally test with
chart.append("circle")
.data(data)
.attr("class", "highlightPoint")
.attr("r",4)
.attr("innerRadius",0)
.style("fill", "pink")
.style("stroke","blue")
.style("stroke-width",1)
.attr("cx", function(d) { return x(d.dist); })
.attr("cy", function(d) { return y(d.ele); })
.attr("display","block") ;
But it display only the first circle.
I don't really understand the function(d) and function(d,i) use :\
Test in http://velo70.ouvaton.org/2013/gpxvtt-un-nouveau-plugin/
It's a little late.. but i need participation points.. :)
For simple handle click mouse and call function on event, I give you a complete file to link with simple function for d3.js..
<script src="js/file.js"></script>
And "THE" File to include ( mainly analyse it for 'on') :
$(function() {
// Handler for .ready() called.
var data = [],
width = 300,
height = 300,
// An array to hold the coordinates
// of the line drawn on each svg.
coords = [],
line = d3.svg.line(),
// Set the behavior for each part
// of the drag.
drag = d3.behavior.drag()
.on("dragstart", function() {
// Empty the coords array.
coords = [];
svg = d3.select(this);
// If a selection line already exists,
// remove it.
//svg.select(".selection").remove();
// Add a new selection line.
svg.append("path").attr({"class": "selection"});
})
.on("drag", function() {
// Store the mouse's current position
coords.push(d3.mouse(this));
svg = d3.select(this);
// Change the path of the selection line
// to represent the area where the mouse
// has been dragged.
svg.select(".selection").attr({
d: line(coords)
});
// Figure out which dots are inside the
// drawn path and highlight them.
selected = [];
svg.selectAll("circle.dot").each(function(d, i) {
point = [d3.select(this).attr("cx"), d3.select(this).attr("cy")];
if (pointInPolygon(point, coords)) {
selected.push(d.id);
}
});
highlight(selected);
})
.on("dragend", function() {
svg = d3.select(this);
// If the user clicks without having
// drawn a path, remove any paths
// that were drawn previously.
if (coords.length === 0) {
// d3.selectAll("svg path").remove();
unhighlight();
return;
}
// Draw a path between the first point
// and the last point, to close the path.
svg.append("line").attr({
"class": "terminator",
d: line([coords[0], coords[coords.length-1]])
});
});
function randomPoint() {
return Math.floor(Math.random()*(width-30)) + 20;
}
// from https://github.com/substack/point-in-polygon
function pointInPolygon (point, vs) {
var xi, xj, i, intersect,
x = point[0],
y = point[1],
inside = false;
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
xi = vs[i][0],
yi = vs[i][1],
xj = vs[j][0],
yj = vs[j][1],
intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
function unhighlight() {
d3.selectAll("circle.dot").classed("highlighted", false);
}
function highlight(ids) {
// First unhighlight all the circles.
unhighlight();
// Find the circles that have an id
// in the array of ids given, and
// highlight those.
d3.selectAll("circle.dot").filter(function(d, i) {
return ids.indexOf(d.id) > -1;
})
.classed("highlighted", true);
}
function Scatter(data, selector, group) {
var svg = d3.select(selector).append("svg")
.attr({
width: width,
height: height
}).call(drag),
g = svg.append("g").attr({"class": "g-dot"}),
// Create a circle element for each
// item in the data passed.
dot = g.selectAll("circle.dot")
.data(data)
.enter().append("circle")
.attr({
"class": "dot",
r: 8,
cx: function(d, i) {
return d[group].x;
},
cy: function(d, i) {
return d[group].y;
},
})
.on("mouseover", function(d, i) {
// Highlight circles on mouseover, but
// only if a path hasn't been drawn.
if (d3.selectAll("svg path").empty()) {
highlight([d.id]);
}
})
.on("mouseout", function(d, i) {
// If a path hasn't been drawn,
// unhighlight the highlighted circles.
if (d3.selectAll("svg path").empty()) {
unhighlight();
}
});
text = g.selectAll("text")
.data(data)
.enter().append("text")
.attr({
x: function(d, i) {
return d[group].x;
},
y: function(d, i) {
return d[group].y + 4;
}
})
.text(function(d, i) {
return d.id;
});
}
// Add the dots to each canvas div.
Scatter(data, "#tableau_principal", "a");
Scatter(data, "#canvas2", "b");
Scatter(data, "#canvas3", "c");
}); // // FIN DOC READY //
// functions generales used partt //
with phonegap 1.5.0rc1 and XCode 4.3.
I can not upgrade my mac for the moment.
When I use plugins I do not have any answer, no alert and no message.
I try to do this :
function onDeviceReady() {
processdiv = document.getElementById('processdiv');
processdiv.innerHTML = "Loading...";
window.plugins.inAppPurchaseManager.onPurchased = function(transactionIdentifier, productId, transactionReceipt) {
console.log('purchased: ' + productId);
/* Give coins, enable subscriptions etc */
}
processdiv.innerHTML += "<br />onPurchased OK";
window.plugins.inAppPurchaseManager.onRestored = function(transactionIdentifier, productId, transactionReceipt) {
console.log('restored: ' + productId);
/* See the developer guide for details of what to do with this */
}
processdiv.innerHTML += "<br />onRestored OK";
window.plugins.inAppPurchaseManager.onFailed = function(errno, errtext) {
console.log('failed: ' + errtext);
}
processdiv.innerHTML += "<br />onFailed OK";
}
function requestProdData(prodStr) {
window.plugins.inAppPurchaseManager.requestProductData(prodStr, function(productId, title, description, price) {
console.log("productId: " + productId + " title: " + title + " description: " + description + " price: " + price);
showAlert("productId: " + productId + " title: " + title + " description: " + description + " price: " + price);
window.plugins.inAppPurchaseManager.makePurchase(productId, 1);
}, function(id) {
console.log("Invalid product id: " + id);
showAlert("par la ?? " + id);
}
);
processdiv.innerHTML = "ProductID: " + prodStr + "<br />";
}
Help
I try to add alert in different place of code to know what is the problem.
I had many products in a test app.
I search example to use this plugins. Thanks.
Do not foget to add plugins inAppPurchaseManager in you plugins Cordova.plist :(
I was currently at this site which shows how to implement business search using the bing map api. But what I am trying to implement is, first the map should get your current location and search for type of business nearby, let's say Restaurant or Check Cashing place.
My current page has the current location working but now how I implement the FindNearBy function with my page?
P.s. I want the search to already take place for the user without having to enter a search text, so the map should load up with current location and right next to it should list all or maybe the closest 5 restaurant nearby.
Not with Bing Maps...you need the Bing Phonebook API to do this.
I can get you part of the way there. The below example combines the use of both the Bing Maps API and the Bing Phonebook API) I just submitted a similar question about how to find the type of business, however...I'm not sure there's a wayto do this :/ (Below example searches for all Starbucks in the area ...of course, some HTML integration is required.
var _map;
var _appId;
$(document).ready(function () {
if (Modernizr.geolocation) {
$(".geofallback").hide();
}
else {
$(".geofallback").show();
}
$.post("Home/GetBingMapsKey", { "func": "GetBingMapsKey" }, function (data) {
// Create a Bing map
_map = new Microsoft.Maps.Map(document.getElementById("map"),
{ credentials: data }); //, mapTypeId: Microsoft.Maps.MapTypeId.ordnanceSurvey
});
// Get the current position from the browser
if (!navigator.geolocation) {
$("#results").html("This browser doesn't support geolocation, please enter an address");
}
else {
$.post("Home/GetBingKey", { "func": "GetBingKey" }, function (data) {
_appId = data;
});
navigator.geolocation.getCurrentPosition(onPositionReady, onError);
navigator.geolocation.getCurrentPosition(Search, onError);
}
});
function onPositionReady(position) {
// Apply the position to the map
var location = new Microsoft.Maps.Location(position.coords.latitude,
position.coords.longitude);
_map.setView({ zoom: 18, center: location });
// Add a pushpin to the map representing the current location
var pin = new Microsoft.Maps.Pushpin(location);
_map.entities.push(pin);
}
function onError(err) {
switch (err.code) {
case 0:
alert("Unknown error :(");
break;
case 1:
alert("Location services are unavailable per your request.");
break;
case 2:
alert("Location data is unavailable.");
break;
case 3:
alert("The location request has timed out. Please contact support if you continue to experience issues.");
break;
}
}
function Search(position) {
// note a bunch of this code uses the example code from
// Microsoft for the Phonebook API
var requestStr = "http://api.bing.net/json.aspx?"
// Common request fields (required)
+ "AppId=" + _appId
+ "&Query=starbucks"
+ "&Sources=Phonebook"
// Common request fields (optional)
+ "&Version=2.2"
+ "&Market=en-us"
+ "&UILanguage=en"
+ "&Latitude=" + position.coords.latitude
+ "&Longitude=" + position.coords.longitude
+ "&Radius=100.0"
+ "&Options=EnableHighlighting"
// Phonebook-specific request fields (optional)
// Phonebook.Count max val is 25
+ "&Phonebook.Count=25"
+ "&Phonebook.Offset=0"
// YP = Commercial Entity, WP = Residential
+ "&Phonebook.FileType=YP"
+ "&Phonebook.SortBy=Distance"
// JSON-specific request fields (optional)
+ "&JsonType=callback"
+ "&JsonCallback=?";
$.getJSON(requestStr, function (data) {
SearchCompleted(data);
});
}
function FormatBingQuery(appId, latitude ) {
}
function SearchCompleted(response) {
var errors = response.SearchResponse.Errors;
if (errors != null) {
// There are errors in the response. Display error details.
DisplayErrors(errors);
}
else {
// There were no errors in the response. Display the
// Phonebook results.
DisplayResults(response);
}
}
function DisplayResults(response) {
var output = document.getElementById("output");
var resultsHeader = document.createElement("h4");
var resultsList = document.createElement("ul");
output.appendChild(resultsHeader);
output.appendChild(resultsList);
var results = response.SearchResponse.Phonebook.Results;
// Display the results header.
resultsHeader.innerHTML = "Bing API Version "
+ response.SearchResponse.Version
+ "<br />Phonebook results for "
+ response.SearchResponse.Query.SearchTerms
+ "<br />Displaying "
+ (response.SearchResponse.Phonebook.Offset + 1)
+ " to "
+ (response.SearchResponse.Phonebook.Offset + results.length)
+ " of "
+ response.SearchResponse.Phonebook.Total
+ " results<br />";
// Display the Phonebook results.
var resultsListItem = null;
var resultStr = "";
for (var i = 0; i < results.length; ++i) {
resultsListItem = document.createElement("li");
resultsList.appendChild(resultsListItem);
//loc is specific to my C# object
var loc = new Array();
loc[0] = results[i].Longitude;
loc[1] = results[i].Latitude;
var address = {
AddressLine1: results[i].Address,
City: results[i].City,
State: results[i].StateOrProvince,
PostalCode: results[i].PostalCode,
Latitude: results[i].Latitude,
Longitude: results[i].Longitude,
Country: results[i].CountryOrRegion,
ID: results[i].UniqueId
};
//this part is specific to my project to return the
//address results so I can store them (since my
//implementation is a demonstration of how to
//use the MongoDB geoNear() functionality
$.ajax({
url: "/Home/AddAddressToCollection",
type: 'post',
data: JSON.stringify(address),
contentType: 'application/json',
dataType: 'json'
});
resultStr = results[i].Business
+ "<br />"
+ results[i].Address
+ "<br />"
+ results[i].City
+ ", "
+ results[i].StateOrProvince
+ "<br />"
+ results[i].PhoneNumber
+ "<br />Average Rating: "
+ results[i].UserRating
+ "<br /><br />";
// Replace highlighting characters with strong tags.
resultsListItem.innerHTML = ReplaceHighlightingCharacters(
resultStr,
"<strong>",
"</strong>");
}
}
function ReplaceHighlightingCharacters(text, beginStr, endStr) {
// Replace all occurrences of U+E000 (begin highlighting) with
// beginStr. Replace all occurrences of U+E001 (end highlighting)
// with endStr.
var regexBegin = new RegExp("\uE000", "g");
var regexEnd = new RegExp("\uE001", "g");
return text.replace(regexBegin, beginStr).replace(regexEnd, endStr);
}
function DisplayErrors(errors) {
var output = document.getElementById("output");
var errorsHeader = document.createElement("h4");
var errorsList = document.createElement("ul");
output.appendChild(errorsHeader);
output.appendChild(errorsList);
// Iterate over the list of errors and display error details.
errorsHeader.innerHTML = "Errors:";
var errorsListItem = null;
for (var i = 0; i < errors.length; ++i) {
errorsListItem = document.createElement("li");
errorsList.appendChild(errorsListItem);
errorsListItem.innerHTML = "";
for (var errorDetail in errors[i]) {
errorsListItem.innerHTML += errorDetail
+ ": "
+ errors[i][errorDetail]
+ "<br />";
}
errorsListItem.innerHTML += "<br />";
}
}
// Bonus: In case you want to provide directions
// for how to get to a selected entity
// _map.getCredentials(function (credentials) {
// $.getJSON('http://dev.virtualearth.net/REST/V1/Routes/driving?' + 'wp.0=' + lat1 + ',' + lon1 + '&wp.1=' + lat2 + ',' + lon2 + '&distanceUnit=mi&optmz=distance&key=' + credentials + '&jsonp=?&s=1',
// function (result) {
// if (result.resourceSets[0].estimatedTotal > 0) {
// var distance = result.resourceSets[0].resources[0].travelDistance;
// }
// else {
// $("#results").html("Oops! It appears one or more of the addresses you entered are incorrect. :( ");
// }
// });
// });
//Tie into a function that shows an input field
//for use as a fallback in case cannot use HTML5 geoLocation
//$(document).ready(function () {
// $("#btnFindLocation").click(function () {
// //check user has entered something first
// if ($("#txtAddress").val().length > 0) {
// //send location query to bing maps REST api
// _map.getCredentials(function (credentials) {
// $.getJSON('http://dev.virtualearth.net/REST/v1/Locations?query=' + $("#txtAddress").val() + '&key=' + credentials + '&jsonp=?&s=1',
// function (result) {
// if (result.resourceSets[0].estimatedTotal > 0) {
// var loc = result.resourceSets[0].resources[0].point.coordinates;
// $("#lat").val(loc[0]);
// $("#lon").val(loc[1]);
// var location = new Microsoft.Maps.Location(loc[0],
// loc[1]);
// _map.setView({ zoom: 18, center: location });
// // Add a pushpin to the map representing the current location
// var pin = new Microsoft.Maps.Pushpin(location);
// _map.entities.push(pin);
// }
// else {
// $("#results").html("sorry that address cannot be found");
// }
// });
// });
// }
// else {
// $("#results").html("please enter an address");
// }
// });
//});