Horizontal scroll bars on programmatic dojox.grid.DataGrid - dojo

How can I keep the horizontal scroll bar from displaying?
An example of what I am attempting is at http://jsfiddle.net/fdlane/gjkGF/3/
Below is an example page of what I am attempting to do. With the width of the container div set to greater than the grid width, I was expecting that the horizontal scroll bars would not be displayed.
Using the current height of 200px and with the number of rows greater than 6, the vertical is displayed (good). However, the horizontal is then also displayed (bad).
What am I missing?
Thanks
fdl
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/tundra/tundra.css" />
<link rel="stylesheet" type="text/css" title="Style" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojox/grid/resources/Grid.css">
<link rel="stylesheet" type="text/css" title="Style" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojox/grid/resources/tundraGrid.css">
<title>Grid Scrolling</title>
</head>
<body class="tundra">
<div id="container" style="width: 350px; height: 200px">
<div id="myGrid">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js"> </script>
<script>
dojo.require("dojo.store.Memory");
dojo.require("dojo.data.ObjectStore");
dojo.require("dojox.grid.DataGrid");
dojo.ready(function () {
var myStore = new dojo.store.Memory({
data: [{ id: "RecId1", values: "fooValue1" },
{ id: "RecId2", values: "fooValue2" },
{ id: "RecId3", values: "fooValue3" },
{ id: "RecId4", values: "fooValue4" },
{ id: "RecId5", values: "fooValue5" },
{ id: "RecId6", values: "fooValue6" },
{ id: "RecId7", values: "fooValue7" },
{ id: "RecId7", values: "fooValue7"}]
});
dataStore = new dojo.data.ObjectStore({
objectStore: myStore
});
var grid = new dojox.grid.DataGrid({
store: dataStore,
structure: [{
name: "ID",
field: "id",
width: "100px"
}, {
name: "Values",
field: "values",
width: "100px"
}]
}, "myGrid");
grid.startup();
});
</script>
</body>
</html>

add this style override to your head element:
<style>
.dojoxGridScrollbox { overflow-x: hidden; }
</style>
Reason may very well be, that when the grid overflows vertically, the vertical (-y) scroller appears and consumes 30 ( or so ) pixels of width, making the grid container also overflow in horizontal orientation
You can try to make use of the grid resize function - if a borderlayout.resize fixes your issue, reason is that it recursively resizes its children (at some calculated abs value). With Grid, you'd see this flow:
resize: function(changeSize, resultSize){
// summary:
// Update the grid's rendering dimensions and resize it
// Calling sizeChange calls update() which calls _resize...so let's
// save our input values, if any, and use them there when it gets
// called. This saves us an extra call to _resize(), which can
// get kind of heavy.
// fixes #11101, should ignore resize when in autoheight mode(IE) to avoid a deadlock
// e.g when an autoheight editable grid put in dijit.form.Form or other similar containers,
// grid switch to editing mode --> grid height change --> From height change
// ---> Form call grid.resize() ---> grid height change --> deaklock
if(dojo.isIE && !changeSize && !resultSize && this._autoHeight){
return;
}
this._pendingChangeSize = changeSize;
this._pendingResultSize = resultSize;
this.sizeChange();
},

Related

How to get data out of a popup on a map with a feature layer from ArcGIS-api for javascript and reuse that data?

I am using a map with feature layers from ArcGIS and the popup to see some data when the user click on a symbol (feature). Is there a way to style the popups exactly the way we want ? In other words, how could I get the data out of the popup, not display the popup but open a modal with that data instead ? Is that even possible ?
This are actually two questions, can you style the popup?, and can you use your own "popup"?.
For the first one, I would say it is pretty customizable, but obviously it depends what you need.
For the second, you just need to stop the default behavior of the view popup, that is to open on right click, and then catch the event yourself to do what you want. Here is an example I made for you that shows that,
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>PopupTemplate - Auto Open False</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.21/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.21/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 500px;
width: 100%;
}
#features {
margin: 20px;
height: 500px;
width: 100%;
overflow: auto;
}
</style>
<script>
var populationChange;
require(["esri/Map", "esri/views/MapView", "esri/layers/Layer"], function (
Map,
MapView,
Layer
) {
const map = new Map({
basemap: "dark-gray"
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 7,
center: [-87, 34]
});
Layer.fromPortalItem({
portalItem: {
id: "e8f85b4982a24210b9c8aa20ba4e1bf7"
}
}).then(function (layer) {
map.add(layer);
view.popup.autoOpenEnabled = false; // <- disable view popup auto open
view.on("click", function (event) { // <- listen to view click event
if (event.button === 0) { // <- check that was left button or touch
view.whenLayerView(layer).then(function (layerView) {
const query = layerView.layer.createQuery();
query.geometry = view.toMap(event);
query.distance = 1;
query.units = "meters";
layerView.queryFeatures(query).then(
response => {
document.getElementById("features").innerText = JSON.stringify(response.features);
console.error(response);
},
err => {
document.getElementById("features").innerText = "Query returns an error, check console to see what happen!.";
console.error(err);
}
);
});
}
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="features"></div>
</body>
</html>

arcGIS 4.18 locate widget custom icon

I have to change the default icon on the Locate widget on arcGIS 4.18. The default icon class is, esri-icon-locate how can I change it to the class, 'esri-icon-navigation'?
I am going through the documentation,
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Locate.html#iconClass
I have tried to use the property, 'iconClass'. But not reflecting in the map icon. Please find the code below,
var locateBtn = new Locate({
view: view,
// iconClass: '\ue666'
iconClass: 'esri-icon-navigation'
});
view.ui.add(locateBtn, {
position: "manual",
});
KER,
You actually right, does not work as expected. Setting iconClass should be the solution.
Funny fact if you check the default iconClass is actually esri-icon-north-navigation, which obviously in not.
Anyway, I am gonna give a dirty solution, just overlap the class you want,
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList += " esri-icon-navigation"
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>Locate button | Sample | ArcGIS API for JavaScript 4.18</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css" />
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script src="https://js.arcgis.com/4.18/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Locate"
], function (Map, MapView, Locate) {
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-56.049, 38.485, 78],
zoom: 3
});
var locateBtn = new Locate({
view: view
});
// Add the locate widget to the top left corner of the view
view.ui.add(locateBtn, {
position: "top-left"
});
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList += " esri-icon-navigation"
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

Limit map area/zoom in arcGIS SceneView

I'm using arcGIS SceneView in local viewing mode to display a WebMap. I'm trying to constrain the zoom level and bounds of an area so that the user can only see the US, Hawaii, and Alaska and cannot pan outside of this. I also need to constrain the zoom level because if the user zooms out too far the over-zoom the map and see untiled/unmapped space.
Are there any potential solves for this? I first thought that using the constraints property might solve it, but it appears the properties that can be fed to this are quite limited:
https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#constraints
One way to achieve what I think you want is:
listen to view property changes,
check constraints,
act accordingly.
Take a look a the example I made for you. In it, I wait for the view to stop updating (updating property), then I check the constraints. If it is out of scale or out of the extent I reset the view. You probably want another action, I just made it simple.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>
View constraints
</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.17/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.17/"></script>
<script>
require([
"esri/Map",
"esri/views/SceneView",
"esri/geometry/Extent"
], function (Map, SceneView, Extent) {
const extent = Extent.fromJSON(
{
"spatialReference": {
"latestWkid":3857,
"wkid":102100
},
"xmin":-13119716.983985346,
"ymin":4024337.3961656773,
"xmax":-13096023.097830579,
"ymax":4030581.302795334
}
);
const MIN_SCALE = 12000;
const MAX_SCALE = 48000;
const map = new Map({
basemap: "topo-vector",
ground: "world-elevation"
});
const view = new SceneView({
container: "viewDiv",
map: map,
viewingMode: "local",
center: [-117.75, 33.99],
scale: 24000
});
function resetView() {
console.log('reset');
view.goTo(
{
center:[-117.75, 33.99],
scale: 24000
}
);
}
view.watch("updating", function (value) {
if (!value) {
if (
// out of scale
view.scale < MIN_SCALE ||
view.scale > MAX_SCALE ||
// out of extent
view.extent.xmin < extent.xmin ||
extent.xmax < view.extent.xmax ||
view.extent.ymin < extent.ymin ||
extent.ymax < view.extent.ymax
) {
resetView();
};
}
});
});
</script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

How to get the coordinates of point where I clicked while using Select interaction?

We use Vue.js and OpenLayers (4.6.5) in our web project. We have a lot of features on the map and some of them are polygons. When I select some particular polygon, its style turns to another color, which means it's highlighted (selected). Of course, I can get the coordinates of selected polygon. But, how can I get the coordinates of point inside that polygon where I clicked?
The code look as following:
markObject (mark) {
if (!mark) {
this.map.un('select', this.onMarkObject)
if (this.markSelection) {
this.markSelection.getFeatures().remove(this.lastSelectedFeature)
this.map.removeInteraction(this.markSelection)
}
return
}
if (!this.markSelection) {
this.markSelection = new Select({
condition: condition.click,
layers: [this.vectorLayer]
})
this.markSelection.on('select', this.onMarkObject)
}
this.map.addInteraction(this.markSelection)
},
onMarkObject (event) {
if (event.selected && event.selected.length > 0) {
const coordinates = event.selected[0].getGeometry().getCoordinates()
}
}
Actually, I've found the solution:
onMarkObject (event) {
const clickCoordinates = event.mapBrowserEvent.coordinate
...
}
Thank you anyway.
What you need is to capture the click event on the map, and then transform pixel to map coordinates, take a look at this example I made for you,
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.1.1/css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
#a { display: none; }
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.1.1/build/ol.js"></script>
<title>Click Pixel Coord</title>
</head>
<body>
<h2>Click on Map to get pixel and coord values</h2>
<p id="p"></p>
<div id="map" class="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
map.on('click', function(evt) {
const coord = map.getCoordinateFromPixel(evt.pixel);
document.getElementById('p').innerHTML =
`Pixel:${evt.pixel[0]} ${evt.pixel[0]}` + '<br>' +
`Coord:${coord[0].toFixed(2)} ${coord[1].toFixed(2)}`;
});
</script>
</body>
</html>

How can I use Sencha Touch widgets along with regular HTML "widgets"?

I have a page that I would like to use some sencha items on along with some non-sencha html.
So the page might be...(after loading sencha headers)
<div id="banner"><h1>#if (Model != null)
{#Model.DisplayName}</h1></div>
<div style="background-color: #CFE1E8; padding: 10px; border: 1px solid black; ">
<div id="buttonDiv"></div>
<script type="text/javascript" src="/Content/js/widgets/button.js"></script>
<div id="searchDiv"></div>
<script type="text/javascript" src="/Content/js/widgets/search.js"></script>
<div id="carouselDiv"></div>
<script type="text/javascript" src="/Content/js/widgets/carousel.js"></script>
<div id="panelDiv"></div>
<script type="text/javascript" src="/Content/js/widgets/panel.js"></script>
</div>
Each of the js files contains some sencha code to render the control into the associated div. For example:
Ext.setup({
fullscreen: false,
onReady: function () {
var panel = new Ext.Panel({
title: 'Message Title',
fullscreen: false,
renderTo: 'buttonDiv',
defaults: {
// applied to each contained item
width: 120
},
items: [
{
xtype: 'button',
text: 'Click Me',
handler: function () {
alert("You Clicked Me...");
}
}
]
});
}
});
The problem I'm having is that when the page is taller than the width of the phone, anytime I touch the screen, the page immediately jumps to the bottom of the page. The normal page scrolling doesn't work at all.
Any suggestions? Thanks.
Try assigning your components a layout and possibly a flex, e.g.:
layout: {
type: 'vbox',
align: 'stretch'
},
and
flex: 1
For scrolling, you could try:
scroll: 'vertical'
Also, another way of using HTML inside sencha is to use the html property in your components, e.g:
new Ext.Panel({
scroll: 'vertical',
layout: {
type: 'vbox',
align: 'stretch'
},
flex: 1
items: [{
html: 'HTML content inside a panel',
}]
});
I ended up doing two things:
Added an Ext.util.Scroller on the body. There's a bug with the Ext.util.Scroller on iPhones that it won't actually let you scroll upwards. Works fine on Androids though.
"Registered" the content of each module's js as a function by pushing to a global variable so that it would get added in the head and then executed them all in a loop, so I only ran Ext.Setup once.