Is there a way to programme bingmap's infobox close button? - bing-maps

In the bingmaps documentation, you can add custom actions to the infobox. I would like to know if there's a similar way to program the default closeButton?
Ideally, I would like to be able to do something like this:
const infobox = new Microsoft.Maps.Infobox(selectedTipCoordinates, {
title: selectedTip.title,
description: selectedTip.description,
closeButton: () => console.log('hello')
});

Unfortunately close event handler could not be customized via InfoboxOptions object, so you could consider either to implement a custom HTML Infobox or override info window click handler. The following example demonstrates how to keep info window opened once close button is clicked and add a custom action:
Microsoft.Maps.Events.addHandler(infobox, 'click', handleClickInfoBox);
function handleClickInfoBox(e){
var isCloseAction = e.originalEvent.target.className == "infobox-close-img";
if(isCloseAction){
//keep info window open..
e.target.setOptions({visible: true});
//apply some custom actions..
console.log("Close button clicked");
}
}
function loadMapScenario() {
var map = new Microsoft.Maps.Map(document.getElementById("myMap"), {
center: new Microsoft.Maps.Location(47.60357, -122.32945)
});
var infobox = new Microsoft.Maps.Infobox(map.getCenter(), {
title: "Title",
description: "Description",
actions: [
{
label: "Handler1",
eventHandler: function() {
console.log("Handler1");
}
},
{
label: "Handler2",
eventHandler: function() {
console.log("Handler2");
}
},
{
label: "Handler3",
eventHandler: function() {
console.log("Handler3");
}
}
]
});
infobox.setMap(map);
Microsoft.Maps.Events.addHandler(infobox, 'click', handleClickInfoBox);
}
function handleClickInfoBox(e){
var isCloseAction = e.originalEvent.target.className == "infobox-close-img";
if(isCloseAction){
//keep info window open..
e.target.setOptions({visible: true});
//apply some custom actions..
console.log("Close button clicked");
}
}
body{
margin:0;
padding:0;
overflow:hidden;
}
<script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?key=&callback=loadMapScenario' async defer></script>
<div id='myMap' style='width: 100vw; height: 100vh;'></div>

No, I don't think there's a way to wire the behavior of default close button differently. That said, you can approximate the desired outcome with a little more work: creating a custom infobox with the same style and then you'll have 100% control:
e.g. (notice the onClick handler on the close button div):
var center = map.getCenter();
var infoboxTemplate = '<div class="Infobox" style=""><a class="infobox-close" href="javascript:void(0)" onClick="function test(){ alert(\'test!\'); } test(); return false;" style=""><img class="infobox-close-img" src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE0cHgiIHdpZHRoPSIxNHB4IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiPjxwYXRoIGQ9Ik03LDBDMy4xMzQsMCwwLDMuMTM0LDAsN2MwLDMuODY3LDMuMTM0LDcsNyw3YzMuODY3LDAsNy0zLjEzMyw3LTdDMTQsMy4xMzQsMTAuODY3LDAsNywweiBNMTAuNSw5LjVsLTEsMUw3LDhsLTIuNSwyLjVsLTEtMUw2LDdMMy41LDQuNWwxLTFMNyw2bDIuNS0yLjVsMSwxTDgsN0wxMC41LDkuNXoiLz48L3N2Zz4=" alt="close infobox"></a><div class="infobox-body" style="max-width: 256px; max-height: 126px; width: 125px;"><div class="infobox-title" >{title}</div><div class="infobox-info" style=""><div>{description}</div></div><div class="infobox-actions" style="display: none;"><ul class="infobox-actions-list"><div></div></ul></div></div><div class="infobox-stalk" style="top: 73.8px; left: 55.5px;"></div></div>';
var infobox = new Microsoft.Maps.Infobox(center, {
htmlContent: infoboxTemplate.replace('{title}', 'myTitle').replace('{description}', 'myDescription'),
offset: new Microsoft.Maps.Point(-64, 16)
});

Related

Bing Maps pushpin icon issues

I have a custom set of icons I'm setting various pins too. When the mouse hovers over them I'd like to bring them to the front and change the style to a different icon.
I use this code to create the pin. OnHover I see the new push pin and on mouseout it returns to how it was. However, it has transparent areas and I can see parts of the non-hover pushpin below it when hovering.
For bringing it to the forefront have tried changing the zIndex value and as far as I can tell it does nothing.
Do I need to refresh the map or something?
Feels like there is something I'm missing.
function createImagePin(location, obj)
{
var smallPin = getSmallPin(obj);
var pin = new Microsoft.Maps.Pushpin(location, {
icon: smallPin.data,
visible: true,
anchor: new Microsoft.Maps.Point(smallPin.width / 2, smallPin.height / 2) //Align center of pushpin with location.
});
pin.dataTarget = obj;
Microsoft.Maps.Events.addHandler(pin, 'mouseover', function (e)
{
if(e.targetType === 'pushpin')
{
var largePin = getLargePin(e.target.dataTarget);
e.target.setOptions({ icon: largePin.data, anchor: new Microsoft.Maps.Point(largePin.width/2,largePin.height/2) });
}
});
Microsoft.Maps.Events.addHandler(pin, 'mouseout', function (e)
{
if (e.targetType === 'pushpin')
{
var smallPin = getSmallPin(e.target.dataTarget);
e.target.setOptions({ icon: smallPin.data, anchor: new Microsoft.Maps.Point(smallPin.width/2,smallPin.height/2) });
}
});
return pin;
}
Currently shapes do no support zIndexing due to performance issues, but there are plans to add support for this. You can however use two layers for your data, the first to store your main data, and the second to display the hovered data. Below is a code sample that demonstrates hovering a pushpin, changing its style and displaying it above all other shapes on the map. When you mouse out the style goes back to what it was and the pushpin goes back to the main layer.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>
<script type='text/javascript'>
var map;
var defaultColor = 'blue';
var hoverColor = 'red';
var mouseDownColor = 'purple';
function GetMap()
{
map = new Microsoft.Maps.Map('#myMap', {
credentials: 'YourBingMapsKey'
});
var layer = new Microsoft.Maps.Layer();
map.layers.insert(layer);
var hoverLayer = new Microsoft.Maps.Layer();
map.layers.insert(hoverLayer);
//Add some random pushpins to fill the map and cover our hoverable main pushpin.
var pushpins = Microsoft.Maps.TestDataGenerator.getPushpins(300, map.getBounds());
layer.add(pushpins);
//Create our hoverable pushpin.
var pin = new Microsoft.Maps.Pushpin(map.getCenter(), {
color: defaultColor
});
layer.add(pin);
Microsoft.Maps.Events.addHandler(pin, 'mouseover', function (e) {
e.target.setOptions({ color: hoverColor });
//Move pin to hover layer.
layer.remove(pin);
hoverLayer.add(pin);
});
Microsoft.Maps.Events.addHandler(pin, 'mousedown', function (e) {
e.target.setOptions({ color: mouseDownColor });
});
Microsoft.Maps.Events.addHandler(pin, 'mouseout', function (e) {
e.target.setOptions({ color: defaultColor });
//Move pin to main layer.
hoverLayer.remove(pin);
layer.add(pin);
});
}
</script>
</head>
<body>
<div id="myMap" style="position:relative;width:600px;height:400px;"></div>
</body>
</html>
You can try this code sample out here: http://bingmapsv8samples.azurewebsites.net/#Pushpin_HoverStyle

How to write <script> in $scope style

I'm implementing google map into my ionic app, and I have a script in my index.html, which, will only allow the map works in the index.html.
But I need my map in my templates file route.html instead, so I believe I should move the script in the index.html to the specific controller.js file, but things here are written in $scope style, can anyone tell me how could I wrote the style into $scope style?
And why actually things won't works in the route.html as the same code is used?
<div id="map"></div>
Here's my script in my index.html:
<script>
function initMap() {
var uluru = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: uluru
});
var marker = new google.maps.Marker({
position: uluru,
map: map
});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=initMap">
</script>
And my controller in the controller.js
.controller('RouteCtrl', function($scope, $ionicLoading) {
$scope.mapCreated = function(map) {
$scope.map = map;
};
$scope.centerOnMe = function () {
console.log("Centering");
if (!$scope.map) {
return;
}
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: false
});
navigator.geolocation.getCurrentPosition(function (pos) {
console.log('Got pos', pos);
$scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
$scope.loading.hide();
}, function (error) {
alert('Unable to get location: ' + error.message);
});
}
})
There 2 ways to solve your problem :
Change your script to angular method in controller or create a service , like:
var marker = new google.maps.Marker({
map: $scope.map,
animation: google.maps.Animation.DROP,
position: latLng
});
var infoWindow = new google.maps.InfoWindow({
content: "Here I am!"
});
google.maps.event.addListener(marker, 'click', function () {
infoWindow.open($scope.map, marker);
});
Change it to jquery in controller, but it not recommend because it will break to purpose of angular usage in ionic:
var map = new google.maps.Map($("#map"), {
zoom: 4,
center: uluru
});

Bing cluster need to display tooltip & popup

Need to display marker bunch(cluster) title on bing map.
And I want to display tooltip#hover and popup#click with cluster is there any option to display with map.
I have tried usign following code (but there is no tooltip and popup on click):
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
credentials: 'Your Bing Maps Key'
});
var pushpin = new Microsoft.Maps.Pushpin(map.getCenter(), null);
var layer = new Microsoft.Maps.Layer();
layer.add(pushpin);
map.layers.insert(layer);
thanks
You can use the infobox class to do this. As luck would have it I was just putting together sample to do this. Here you go:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type='text/javascript'
src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap'
async defer></script>
<script type='text/javascript'>
var map, infobox, tooltip;
var tooltipTemplate = '<div style="background-color:white;height:20px;width:150px;padding:5px;text-align:center"><b>{title}</b></div>';
function GetMap() {
map = new Microsoft.Maps.Map('#myMap', {
credentials: Your Bing Maps Key'
});
//Create a second infobox to use as a tooltip when hovering.
tooltip = new Microsoft.Maps.Infobox(map.getCenter(), {
visible: false,
showPointer: false,
showCloseButton: false,
offset: new Microsoft.Maps.Point(-75, 10)
});
tooltip.setMap(map);
//Create an infobox at the center of the map but don't show it.
infobox = new Microsoft.Maps.Infobox(map.getCenter(), {
visible: false
});
//Assign the infobox to a map instance.
infobox.setMap(map);
//Create random locations in the map bounds.
var randomLocations = Microsoft.Maps.TestDataGenerator.getLocations(5, map.getBounds());
for (var i = 0; i < randomLocations.length; i++) {
var pin = new Microsoft.Maps.Pushpin(randomLocations[i]);
//Store some metadata with the pushpin.
pin.metadata = {
title: 'Pin ' + i,
description: 'Discription for pin' + i
};
//Add a click event handler to the pushpin.
Microsoft.Maps.Events.addHandler(pin, 'click', pushpinClicked);
Microsoft.Maps.Events.addHandler(pin, 'mouseover', pushpinHovered);
Microsoft.Maps.Events.addHandler(pin, 'mouseout', closeTooltip);
//Add pushpin to the map.
map.entities.push(pin);
}
}
function pushpinClicked(e) {
//Hide the tooltip
closeTooltip();
//Make sure the infobox has metadata to display.
if (e.target.metadata) {
//Set the infobox options with the metadata of the pushpin.
infobox.setOptions({
location: e.target.getLocation(),
title: e.target.metadata.title,
description: e.target.metadata.description,
visible: true
});
}
}
function pushpinHovered(e) {
//Hide the infobox
infobox.setOptions({ visible: false });
//Make sure the infobox has metadata to display.
if (e.target.metadata) {
//Set the infobox options with the metadata of the pushpin.
tooltip.setOptions({
location: e.target.getLocation(),
htmlContent: tooltipTemplate.replace('{title}', e.target.metadata.title),
visible: true
});
}
}
function closeTooltip() {
tooltip.setOptions({
htmlContent: ' ',
visible: false
});
}
</script>
</head>
<body>
<div id="myMap" style="position:relative;width:600px;height:400px;"></div>
</body>
</html>

How to override event handler function of child component from parent component in react.js

/** #jsx React.DOM */
var Button = React.createClass({
handleClick: function(){
console.log(' FROM BUTTON')
},
render: function() {
return <input type='button' onClick={this.handleClick} value={this.props.dname}/>;
}
});
var Text = React.createClass({
render: function() {
return <input type='text' onClick={this.handleClick} value={this.props.ival}/>;
}
});
var search = React.createClass({
handleClick: function() {
console.log('searching')
},
render: function(){
return (
<div>
<Text/>
<Button dname={this.props.dname} onClick={this.handleClick} />
</div>
);
}
});
React.renderComponent(<search dname='Look up' fname='Search'/> , document.body);
I have created a button and text component and included them in a search component now i want to override the default handleClick event of button with search component's handler.
But this.handleClick is pointing to button component's event handler.. please help..
i need FROM SEARCH on click instead i got FROM BUTTON..
You are 99% percent there.
React uses a one-way data-flow. So, events on nested components will not propagate to their parents.
You must propagate events manually
Change your <Button>s handleClick function to call the this.props.handleClick function passed in from it's <Search> parent:
var Button = React.createClass({
handleClick: function () {
this.props.onClick();
},
...
});
Attached is a fiddle of your original post, with the required change. Instead of logging FROM BUTTON, it will now alert searching.
http://jsfiddle.net/chantastic/VwfTc/1/
You need to change your Button component to allow such behaviour:
var Button = React.createClass({
handleClick: function(){
console.log(' FROM BUTTON')
},
render: function() {
return (
<input type='button'
onClick={this.props.onClick || this.handleClick}
value={this.props.dname} />
);
}
});
note the onClick={this.props.onClick || this.handleClick}.
That way if you pass an onClick prop when instantiating Button it will have a preference over the Button's handleClick method.
Or if you can execute both of them, you can put
class Button extends React.Component {
handleClick = () => {
console.log("from buttom");
if (this.props.hasOwnProperty('onClick')){
this.props.onClick();
}
};
You would check whether the object has the specified property and run it

How show external toolbar programmatically

I need to programmatically set the focus to an editor instance after initializing it.
The box gets focus and you can start typing but the external toolbar is not shown unless you click in the editor frame.
I tryed to change some css settings and the toolbar is shown but it disappear when clicking on editor frame.
var toolbar = $('#' + ed.id + '_external').hide().appendTo("#tiny_toolbar");
toolbar.show();
toolbar.css('top','50px');
toolbar.css('display','block');
$(".defaultSkin,.mceExternalToolbar").css("position","").css("z-index","1000");
Is there a way to simulate the editor click via js code so the toolbar would be displayed correctly?
Update:
No, I'm not wrong!
The tiny iframe appear on different top,left of my text container.
This code will explain better which is the problem.
<html>
<head>
<script type="text/javascript" src="js/lib/jquery.js"></script>
<script type="text/javascript" src="js/lib/jquery-ui.js"></script>
<script src="js/lib/tiny/tiny_mce.js"></script>
<script type="text/javascript">
function initTiny(){
tinyMCE.init({
language: false,
mode: "none",
theme: "advanced",
dialog_type: "modal",
theme_advanced_buttons1: ",bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "none",
theme_advanced_path: "none",
theme_advanced_toolbar_location: "external",
setup: function (ed) {
ed.onInit.add(function (ed) {
var visible = 1;
var tout = null;
var $toolbar = $('#' + ed.id + '_external');
$toolbar.css('top', '50px');
$toolbar.css('display', 'block');
$toolbar.hide();
$toolbar.show();
var show = function () {
tout && clearTimeout(tout);
tout = setTimeout(function () {
tout = null;
$toolbar.css({
top: "50px",
display: 'block'
});
visible = 1;
}, 250);
};
$(ed.getWin()).bind('click', function () {
if (ed.isHidden()) {
show();
}
});
})
}
});
}
$(document).ready(function(){
initTiny();
$('#content3').click(function(){
tinyMCE.execCommand("mceAddControl", false, 'content3');
});
$('html').click(function(){
tinyMCE.execCommand("mceRemoveControl", false, 'content3');
});
});
</script>
</head>
<body>
<div id="tiny_toolbar" class="defaultSkin" style="position:relative;"> toolbar </div>
<div id="content3" style="top:120px;left:180px;width:180px;height:200px;border:1px solid;position:absolute;">
<p>CONTENT 3!</p>
</div>
</body>
</html>
No, I'm not wrong!
The tiny iframe appear on different top,left of my text container.
This code will explain better which is the problem.
<html>
<head>
<script type="text/javascript" src="js/lib/jquery.js"></script>
<script type="text/javascript" src="js/lib/jquery-ui.js"></script>
<script src="js/lib/tiny/tiny_mce.js"></script>
<script type="text/javascript">
function initTiny(){
tinyMCE.init({
language: false,
mode: "none",
theme: "advanced",
dialog_type: "modal",
theme_advanced_buttons1: ",bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "none",
theme_advanced_path: "none",
theme_advanced_toolbar_location: "external",
setup: function (ed) {
ed.onInit.add(function (ed) {
var visible = 1;
var tout = null;
var $toolbar = $('#' + ed.id + '_external');
$toolbar.css('top', '50px');
$toolbar.css('display', 'block');
$toolbar.hide();
$toolbar.show();
var show = function () {
tout && clearTimeout(tout);
tout = setTimeout(function () {
tout = null;
$toolbar.css({
top: "50px",
display: 'block'
});
visible = 1;
}, 250);
};
$(ed.getWin()).bind('click', function () {
if (ed.isHidden()) {
show();
}
});
})
}
});
}
$(document).ready(function(){
initTiny();
$('#content3').click(function(){
tinyMCE.execCommand("mceAddControl", false, 'content3');
});
$('html').click(function(){
tinyMCE.execCommand("mceRemoveControl", false, 'content3');
});
});
</script>
</head>
<body>
<div id="tiny_toolbar" class="defaultSkin" style="position:relative;"> toolbar </div>
<div id="content3" style="top:120px;left:180px;width:180px;height:200px;border:1px solid;position:absolute;">
<p>CONTENT 3!</p>
</div>
</body>
</html>
I'm using TinyMCE 4 and I needed an external Toolbar with my app.
I initially only set the "fixed_toolbar_container" and the "inline" properties but my toolbar kept on disappearing when my editor text area was not in focus.
So, in the INIT I changed the following:
In the "INIT" I set "inline" to "true" and "fixed_toolbar_container" to the selector for my external toolbar div.
In the "SETUP" function I prevented the propagation of the "blur" event.
This seemed to work for me but I'm not entirely sure if preventing the default behavior on blur will have any adverse consequences. I'll update this post if I find something.
Hope this helps. :)
tinyMCE.init({
...
inline: true,
fixed_toolbar_container: "div#ToolBar",
// Set the mode & plugins
nowrap: false,
statusbar: true,
browser_spellcheck: true,
resize: true,
...
setup: function (editor) {
// Custom Blur Event to stop hiding the toolbar
editor.on('blur', function (e) {
e.stopImmediatePropagation();
e.preventDefault();
});
}
})
In your tinymce init use
...
theme_advanced_toolbar_location: "external",
setup : function(ed) {
ed.onInit.add(function(ed, evt) {
var $toolbar = $('#'+ed.id + '_external');
$toolbar.css('top','50px');
$toolbar.css('display','block');
$toolbar.hide();
$toolbar.show();
});
});
You should also use a timeout to call the following functions (i.e. show() onclick)
var visible = 1;
var tout = null;
var show = function() {
tout && clearTimeout(tout);
tout = setTimeout(function() {
tout = null;
$toolbar.css({ top : $window.scrollTop(), display : 'block' });
visible = 1;
}, 250);
};
var hide = function() {
if (!visible) { return; }
visible = 0;
$toolbar.hide();
};
$(ed.getWin()).bind('click', function() {
show();
});