GeoJSON map fails to display in .Net MVC2 view - asp.net-mvc-2

The JavaScript worked just fine when I was running it in a straight HTML page on a local server. But, when I moved it to the .aspx page it no longer displays. Firebug shows no script errors and I know the map data is loading because it lists the attributes on the page properly. But, the map itself does not display. The zoom icon typically in the corner does not display either, the element is left untouched. It didn't work in IE either.
Here is the code for the initialization, it calls when the window loads.
function init() {
var map = new OpenLayers.Map('map', {
allOverlays: true
});
countries = new OpenLayers.Layer.Vector("Countries", {
protocol: new OpenLayers.Protocol.HTTP({
url: "../../Content/simplify3.geojson",
format: new OpenLayers.Format.GeoJSON({
extractAttributes: true,
visibility: true
})
}),
strategies: [new OpenLayers.Strategy.Fixed()]
});
map.addLayer(countries);
select = new OpenLayers.Control.SelectFeature(countries,
{ multiple: true, toggle: true });
countries.events.on({
"featureselected": onFeatureSelect,
"featureunselected": onFeatureUnselect,
"loadend": populateList
});
map.addControl(select);
select.activate();
map.zoomToMaxExtent();
}
The map should go here:
<div id="map" style="width: 800px; height: 400px; border: 2px solid black;">There Should Be A Map Here!</div>
Any thoughts other than shooting the damn thing?

Related

Leaflet Draw preventing click on elements while is active

I have several days fighting this with no luck. I'm using leaflet 1.4.0 along with leaflet.draw 1.0.4. Instead of using the L.control.draw UI, I'm using my own buttons to create polygons and rectangles. It works perfectly on desktop browsers (except IE, of course), but fails on iPads, Android tablets (I've not checked on phones), even if you switch the latest Chrome to emulate a mobile device (using the 'toogle device toolbar' on the dev tools) it fails.
I have created this jsfiddle to illustrate the problem: https://jsfiddle.net/fsv8jegd/2/
Using Chrome with the 'toggle device' off, click on the 'start poly' button. Cursor changes to a cross and a label 'click and drag to draw rectangle'. Click on the 'cancel' button, the cursor goes back to the regular arrow.
Now turn on 'toggle device' on Chrome dev tools and choose 'responsive' or any of the 'iPhone' or 'iPads'. Click on the 'start poly' button. Cursor changes to the cross. Try to click on the 'cancel' button. Nothing happens. It doesn't receive the click event. The only way to cancel this is actually drawing the rectangle.
Any ideas?
Thanks!
html:
<div id="map"> </div>
<button class='buttons' type="button" style="top:0" onclick="startpoly()">START POLY</button>
<button class='buttons' type="button" style="top:20px" onclick="cancelpoly()">CANCEL</button>
css:
#map { height: 200px !important; width: 80%; }
.buttons {position: absolute; left: 0; z-index: 999999}
JS:
polygon_query_options = { shapeOptions: { stroke: true, color: '#6e83f0', weight: 4, opacity: 0.9, fill: true, fillColor: null, fillOpacity: 0.2, clickable: false, dashArray: '10,10' } };
$(document).ready(function() {
map = L.map('map', { preferCanvas: true, zoomControl: true, zoom: 10, maxZoom: 20, center: [29.8, -95.5]});
var drawnItems = new L.FeatureGroup();
drawnItems.addTo(map);
drawnItems.bringToFront();
L.Browser.touch = true;
var baseMapGroup = new L.featureGroup();
basemapLayer = L.tileLayer('https://cartodb-basemaps-d.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { attribution: 'CartoDB', maxZoom: 20, maxNativeZoom: 20 });
basemapLabelLayer = L.tileLayer('https://cartodb-basemaps-d.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', { attribution: 'CartoDB', maxZoom: 20, maxNativeZoom: 20 });
basemapLabelLayer.addTo(map);
basemapLabelLayer.bringToBack();
basemapLayer.addTo(map);
basemapLayer.bringToBack();
map.on('draw:created', function (e) {
var layer = e.layer;
drawnItems.addLayer(layer);
});
});
function startpoly() {
polygonDrawer = new L.Draw.Rectangle(map, polygon_query_options);
polygonDrawer.enable();
};
function cancelpoly() {
if (polygonDrawer != undefined) { polygonDrawer.disable(); }
};
I found this is a bug on the leaflet.draw library. So I followed the trail, and in the line 1260 of the leaflet.draw 1.0.4 the following code causes the problem:
document.addEventListener('touchstart', L.DomEvent.preventDefault, { passive: false });
I replaced that line with this code:
var tempMap = document.getElementById("map");
tempMap.addEventListener('touchstart', L.DomEvent.preventDefault, { passive: false });
Basically instead of preventing the touchstart event on the document, now is applied only to the map object.
Hope this helps anyone out there.

How can I pass a dynamic height to Leaflet CRS map in my Ionic 3 App?

I am using Leaflet to render a floor plan map on my page. I am able to render my image, but because a user can upload any size of map, I need to be able to account for that.
I am capturing the height/width when the image is uploaded, but not sure how to pass that to my view.
I am trying this (without much luck):
<div #map id="map" ng-style="{'height' : '{{ myObject.mapHeight }}px' }"></div>
mapHeight is available in my .ts file. and I can output it to the view to check that a value is actually coming through. What is the best way to pass the image height to the view?
Here is my .ts file:
map: L.Map = null;
#ViewChild('map') mapContainer: ElementRef;
...
this.map = L.map(this.mapContainer.nativeElement, {
crs: L.CRS.Simple,
});
let geoJson = L.geoJSON(this.geoData, {
style: function (feature) {
return {
weight: 0.8
}
},
onEachFeature: function (feature, layer) {
//
}
}).addTo(this.map);
let bounds: any = [[0, 0], [this.myObject.mapHeight, this.myObject.mapWidth]];
let image: any = L.imageOverlay(this.myObject.mapUrl, bounds).addTo(this.map);
this.map.fitBounds(bounds);
EDIT
If I do this, I can get the height, but watching the logs, it seems this method just runs and runs and runs. I can immagine at some point I'll consume all memory and that's no good.
<div #map id="map" [ngStyle]="getMapStyle()"></div>
.ts
...
getMapStyle() {
console.log('--> getMapStyle called');
console.log('map height: ', this.mapHeight + 'px');
return {
'height': this.myObject.mapHeight + 'px'
};
}
For anyone else trying to do the same, here is what ended up working for me.
.html
<div #map id="map" [style.height.px]="myObject?.mapHeight"></div>

How can I add an icon to switch the mapboxgl style dynamically?

I want to add an icon as below in the mapboxgl view. Working with Angular2
When I click the icon it should automatically switch the styles (streets-v9, satelllite-v9)
I am following the link mapboxgl example
Did you see this API method?
https://www.mapbox.com/mapbox-gl-js/api/#map#setstyle
With that you can set a new style for the map when you e.g. click an icon or press a button or what ever you wish.
Take this as a reference to build upon:
https://jsfiddle.net/andi_lo/706pot8L/
mapboxgl.accessToken = 'pk.eyJ1IjoiZmFyYWRheTIiLCJhIjoiTUVHbDl5OCJ9.buFaqIdaIM3iXr1BOYKpsQ';
let map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-1.77, 52.73],
zoom: 3,
});
let icon = document.getElementById('icon');
icon.addEventListener('click', function(e) {
map.setStyle('mapbox://styles/mapbox/light-v9');
}, false)
#icon {
position: absolute;
top: 15px;
left: 15px;
color: black;
}
#map {
height: 500px;
}
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.38.0/mapbox-gl.css" rel="stylesheet"/>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.38.0/mapbox-gl.js"></script>
<div id="map"></div>
<button id="icon">
Switch layers
</button>
What you want is a "control" that switches layers. Mapbox-GL-JS doesn't include such a thing, nor is there one listed as a plugin (yet).
You should use Mapbox-GL-JS's iControl class to create the control, then add styling and behaviour following Mapbox's instructions:
function LayerSwitchControl() { }
LayerSwitchControl.prototype.onAdd = function(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'mapboxgl-ctrl';
// change this next line to include a layer-switching icon
this._container.textContent = 'Hello, world';
return this._container;
};
LayerSwitchControl.prototype.onRemove = function () {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
};
You'll then need to add code to:
Add the control
Respond to click events as appropriate.
This is my working code,
This is zoom level control

Page automatically go to the top when opening a dynamic jquery dialog box first time

I am developing a Task pane word add-in using JavaScript API, I have used below code to create a jQuery dialogbox dynamically using a function:
function myConfirm(dialogText, okFunc, cancelFunc, dialogTitle) {
$('<div style="padding: 10px; max-width: 500px; word-wrap: break-word;">'
+ dialogText + '</div>').dialog({
draggable: true,
modal: true,
resizable: false,
width: 'auto',
title: dialogTitle || 'Confirm',
minHeight: 75,
position: {
my: "center",
at: "center",
of: window
},
buttons: {
OK: function() {
if (typeof(okFunc) == 'function') {
setTimeout(okFunc, 50);
}
$(this).dialog('destroy');
},
Cancel: function() {
if (typeof(cancelFunc) == 'function') {
setTimeout(cancelFunc, 50);
}
$(this).dialog('destroy');
}
}
});
}
But when i open it first time to call myConfirm function, the page scroll goes to top and when i scroll down to click on dialog-box it again send the scroll back to top then i need to again scroll down, now i am able to click on dialog-box buttons. it works fine after first.
I need to set dynamically text of box and function on button clicks so i am creating it dynamically. I have also test it on Internet Explorer, it's working fine.
Please advice how i can fix it for word add-in.
You can try below code when you are calling your function :-
onclick="myConfirm();return false;"
Just add "return false;" after your function name as shown above.
Edit 1:-
Or you can return false from your function as well.
Edit 2 :-
$form.show().dialog({
close: function (event) { event.preventDefault(); }
resizable: false,
etc....
});

Does codemirror provide Cut, Copy and Paste API?

From http://codemirror.net/doc/manual.html, I only find getRange(),
undo(), redo() etc, and I can't find cut(), copy() and paste API,
and more when I try to run editor.execCommand("cut"), I get the error.
Could you help me? Thanks!
Using clipboard.js, you can define the text() function to grab the value of the CodeMirror's inner document.
Store a reference to the (<textarea>) editor's selector for convenience.
var editorSelector = '#editor' // or '#editor + .CodeMirror';
Instantiate a new ClipBoard object with reference to your button.
new Clipboard('.clip-btn-native', {
text: function(trigger) {
return getCodeMirrorNative(editorSelector).getDoc().getValue();
}
});
Retrieve a CodeMirror Instance via native JavaScript.
function getCodeMirrorNative(target) {
var _target = target;
if (typeof _target === 'string') {
_target = document.querySelector(_target);
}
if (_target === null || !_target.tagName === undefined) {
throw new Error('Element does not reference a CodeMirror instance.');
}
if (_target.className.indexOf('CodeMirror') > -1) {
return _target.CodeMirror;
}
if (_target.tagName === 'TEXTAREA') {
return _target.nextSibling.CodeMirror;
}
return null;
};
Demo
Please see complete; in-depth demo over at JSFiddle.
There are no CodeMirror APIs for cut/copy/paste because browser security restrictions forbid JavaScript from accessing the clipboard programmatically. Paste could be used to steal private data and Cut/Copy can be used as a more elaborate attack vector.
The browser's own native code handles user gestures that access the clipboard (keyboard shortcuts and context menu items), based solely on the currently selected text or focused text field.
This SO thread has a good summary of attempts to work around these restrictions. CodeMirror's approach is the first bullet: it uses a hidden textarea to ensure that user clipboard gestures work, but that still doesn't support programmatic APIs.
But there is a partial workaround: use a small Flash widget (this is the 2nd bullet in the thread above). Flash relaxes the restrictions on Copy/Cut (but not Paste) a bit. It still has to be triggered by some user event, but it could be something like clicking a button in your HTML UI. Wrappers like ZeroClipboard and Clippy make it simple to access to these capabilities without needing to know Flash. You'd need to write a little glue code to pull the appropriate string from CodeMirror when copying, but it shouldn't be too bad.
Add a hidden contenteditable div to your textarea editor wrapper. Contenteditable divs respect new lines and tabs, which we need when copying code.
Here is my CodePen demo
var content = $('.content');
var toCopy = content.find('.copy-this');
// initialize the editor
var editorOptions = {
autoRefresh: true,
firstLineNumber: 1,
lineNumbers: true,
smartIndent: true,
lineWrapping: true,
indentWithTabs: true,
refresh: true,
mode: 'javascript'
};
var editor = CodeMirror.fromTextArea(content.find(".editor")[0], editorOptions);
content[0].editor = editor;
editor.save();
// set editors value from the textarea
var text = content.find('.editor').text();
editor.setValue(text);
// setting with editor.getValue() so that it respects \n and \t
toCopy.text(editor.getValue());
$(document).on('click', '.copy-code', function() {
var content = $(this).closest('.content');
var editor = content[0].editor;
var toCopy = content.find('.copy-this')[0];
var innerText = toCopy.innerText // using innerText here because it preserves newlines
// write the text to the clipboard
navigator.clipboard.writeText(innerText);
});
.content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.CodeMirror {
height: fit-content !important;
}
.copy-code {
background: #339af0;
width: fit-content;
cursor: pointer;
}
<!-- resources -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/codemirror.css" />
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.40.0/mode/javascript/javascript.min.js"></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<!-- button to copy the editor -->
<div class="copy-code" title="copy code">copy</div>
<!-- add contenteditable div as it respects new lines when copying unlike textarea -->
<div class="copy-this" contenteditable style="display: none"></div>
<textarea class="editor" style="display: none;">// here is a comment
// here is another comment
</textarea>
</div>