How to place a HTML element on a map in OpenLayers - dom

I am working on Openlayers 5.13 with jQuery 3.21. I am trying to place a html div element on the viewport of a map in openlayers. This element is supposed to have two check-boxes to filter out some content on the map.
For this purpose I am using an Overlay instance.
There are two problems:
1) When I zoom-in or zoom-out the overlay tends to increase and decrease in size, which is not what I am expecting.
I want that overlay (html div element) to retain its size.
2) I cant quit figure out how to place the overlay in top right corner.
An overlay is instantiated with a position property which I don't know what to set to.
I also don't know that if the overlay is what I should seek to show some static element on the map. (I highly doubt that overlay is right way)
Here is my code :
css-
<style>
.ol-panel {
position: absolute;
background-color: white;
filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
min-width: 100px;
}
</style>
html -
<div id="panel" class="ol-panel">
<div id="content">
<table>
<tr>
<td>
Ports <input type="checkbox">
</td>
</tr>
<tr>
<td>
Vessels <input type="checkbox">
</td>
</tr>
</table>
</div>
</div>
<div id="map"></div>
script -
map = new ol.Map({
logo: 'false',
target: 'map',
layers: [new ol.layer.Tile({
title: 'OSM',
type: 'base',
visible: true,
source: new ol.source.OSM()
})],
view: new ol.View({
center: ol.proj.transform([17.813988, 43.342019], 'EPSG:4326', 'EPSG:3857'),
zoom: 3
})
});
panelDiv = document.getElementById("panel");
var panel = new ol.Overlay({
element: panelDiv,
stopEvent: false,
//offset:[0,0],
autoPan: true,
position: ol.proj.transform([82,80 ], 'EPSG:4326', 'EPSG:3857'),
positioning: 'top-right',
autoPanAnimation: {
duration: 250
}
});
map.addOverlay(panel);
This is my current output:
This is what I am expecting, an element that stays fixed at a position:
Reference - [http://openlayers.org/en/latest/apidoc/module-ol_Overlay-Overlay.html]

I got what I was looking for here [http://openlayers.org/en/latest/examples/custom-controls.html?q=custom-controls]
/** Create a checkbox to toggle visibility of straits on map
* You can create different controls for different operations
*/
var strait_cbx = document.createElement('input');
strait_cbx.type = "checkbox";
strait_cbx.id = "strait_cbx";
strait_cbx.checked = true;
/**
* This is a container element which holds input elements which are controls for the map
* You can add as many as you want depending upon use.
* The element is a div which would act like a panel to add controls on map like toggling visibility of the layers
*/
var element = document.createElement('div');
element.className = 'ol-control-panel ol-unselectable ol-control';
element.innerHTML="<b>Straits</b> "
element.appendChild(strait_cbx);
/*A custom control which has container holding input elements etc*/
var controlPanel = new ol.control.Control({
element: element
});
map.addControl(controlPanel);

Related

Add a div element on Leaflet map

I need to add my favorite text to middle-top of my map div, so I have:
<div id="map" style="height:300px;">
<div style="width:150px;background-color:red; z-index:1000;"> Hello World !!</div>
</div>
And this is my simplified JS code:
<script>
$(document).ready(function () {
var Lat = 32.646540;
var Lon = 51.667743;
map = L.map('map').setView([Lat, Lon], 19);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Thanks to OSM',
maxZoom: 19
}).addTo(map);
});
</script>
And the problem is that the Red Text goes behind the map and I can't manage it.
Before loading the map :
After loading the map :
add your Hello World div a higher z-index like z-index: 9999
Update
Now I see it. You add the hello World div as child to the map. You have to add it as sibling.
<div class="box"> Hello World</div>
<div id="map" style="height:300px;"></div>
CSS:
.box{
position: absolute;
top: 0;
z-index: 9999;
text-align: center;
width: 150px;
left: 50%;
margin-left: -75px; /* half of the width */
background-color:red;
}

How to implement drag&drop functionality in ace-editor

I want to add drag&drop functionality into the ace-editor. I have a sidebar contains some objects, what I want to do is I can drag the object from the sidebar and drop it on the ace-editor.
Set text data when object starts dragging, ace will insert that text when dropping element onto it.
// create
document.querySelector("#drag").ondragstart = function(e) {
var dataTransfer = e.dataTransfer;
dataTransfer.effectAllowed
dataTransfer.setData("Text", e.target.outerHTML + "\n");
}
// create editor
var editor = ace.edit(null, {
maxLines: 10,
minLines: 5,
})
document.body.appendChild(editor.container)
#drag {
padding: 10px
}
#drag>span {
padding: 3px;
border: solid 1px purple;
cursor: grab;
}
<script src=https://ajaxorg.github.io/ace-builds/src-noconflict/ace.js></script>
<div id=drag>
<span draggable=true >Drag Me</span>
<span draggable=true >Or Me</span>
</div>

JQuery Class selector not working on Zoom plugin

I've been trying to get jQuery to select a particular element in the JQuery zoom plugin but it doesnt seem to be working
This is the html markup for the zoom region
<div class="zoom" style="width: 60% !important; display: block; position: fixed; overflow: hidden;">
<img src="//cdn.shopify.com/s/files/1/0456/6809/t/3/assets/bx_loader.gif?27021" alt="" class="abs-center-translate loader">
<img src="//cdn.shopify.com/s/files/1/0456/6809/products/568A.jpeg?v=1413437903" class="zoomImg" style="position: absolute; top: -1385.54456824513px; left: -389.68108776267px; opacity: 1; width: 682.5px; height: 1024px; border: none; max-width: none; max-height: none;">
</div>
function showZoomImgSmaller(img) {
var zoomsmall = $('.zoom');
zoomsmall.empty();
zoomsmall.append('{{ "bx_loader.gif" | asset_url | img_tag: "", "abs-center-translate loader" }}');
$('.collectionZoomContainer').show();
zoomsmall.attr( "style","width:60%!important" );
var zoomsmallimg= $('.zoom > img');
console.log(zoomsmallimg.next().get());
$('.zoomImg').attr("style","max-width:500px!important");
zoomsmall.show();
zoomsmall.zoom({url: img, magnify: 0.5});
}
The console returns just a [] for the .zoomImg.get() and an undefined for a .zoomImg.html()
I want to change the css of this particular element and can only do it through jquery.
Any help will be greatly appreciated. Thanks
There is a lot going on here that I cannot see, but my guess is that when you call empty() on your div, you are removing all children of the div (including the .zoomImg class which you are trying to look up later). Instead of removing all elements, you might just want to remove the first image:
function showZoomImgSmaller(img) {
var zoomsmall = $('.zoom');
$('.zoom > .loader').remove(); //change is here
zoomsmall.append('{{ "bx_loader.gif" | asset_url | img_tag: "", "abs-center-translate loader" }}'); //angular? not sure what this does
$('.collectionZoomContainer').show(); //not sure what this
zoomsmall.attr( "style","width:60%!important" );
var zoomsmallimg= $('.zoom > img');
console.log(zoomsmallimg.next().get());
$('.zoomImg').attr("style","max-width:500px!important");
zoomsmall.show();
zoomsmall.zoom({url: img, magnify: 0.5});
}
Hey so I managed to get my style applied by appending css in the head of the page. This style was applied even though the element didnt exist till later.
This is the code I used.
$("<style type='text/css'> .zoomImg{ max-width:200px!important;} </style>").appendTo("head");
Cheers.

jQuery UI Sortable, how to fix the list height?

I'm using jQuery UI "sortable" plugin to be able to select and sort items.
I set up the plugin to have two lists, one for "available" items, the second for "selected" items.
The plugin works as expected, I can move items from one list to the other.
However, when I remove one item from the list, the height of the list is lowered. Is there any way to fix it?
In fact, i'd like to set the outer border of both list to the initial height of the left items (at the beginning, all items are in the first list)
This picture describe what I want to do:
The red lines are what I'd like. I want both lists to have this size, fixed.
Here is my code (generated from an asp.net webpage actually) :
<script type="text/javascript">
$(function () {
$("#sourceItems").sortable({
connectWith: "#targetItems",
update: function (event, ui) {
$("#selectedUserIDs").val(
$("#targetItems").sortable('toArray')
);
},
placeholder: "ui-state-highlight"
});
$("#targetItems").sortable({
connectWith: "#sourceItems",
placeholder: "ui-state-highlight"
});
$("#sourceItems, #targetItems").disableSelection();
});
</script>
<style type="text/css">
#sourceItems, #targetItems { list-style-type: none; margin: 0; padding: 0; margin-right: 10px; background: #eee; padding: 5px; width: 230px; border:solid 1px black; }
#sourceItems li, #targetItems li { margin: 5px; padding: 5px; width: 200px; height: 12px; }
</style>
<div style="float: left; display: inline-block; width:fill-available">
<p>Available :</p>
<ul id="sourceItems" class="droptrue">
<li class="ui-state-default" id='i1'>item1</li>
<li class="ui-state-default" id='i32'>item2</li>
<li class="ui-state-default" id='i47'>item3</li>
<li class="ui-state-default" id='i46'>item4</li>
</ul>
</div>
<div style="float: left; display: inline-block;">
<p>Selected :</p>
<ul id="targetItems" class="droptrue">
</ul>
</div>
<div style="display: none">
<input name="selectedUserIDs" type="text" id="selectedUserIDs" />
</div>
The hidden input field is my container for storing selected items (posted with the form).
I've tried by adding .height($("#sourceItems).outerHeight()); to both lists, but this does not works.
I came here looking for a similar, but more generalized solution to the same problem. The solution here didn't help me, but I figured it out on my own and thought it might be helpful to share it.
I didn't want the two sortable lists to be fixed, I just wanted them to stay the same height. When you are dealing with a large number of items, having two dynamically sized boxes around the list can make it hard to work with, as the one box is so much smaller than the other. Making both boxes a fixed height is also less than optimal, as then you end up with scrollbars once your number of items in one list exceeds that height. I wanted both boxes to dynamically expand using the built-in functionality of the JQuery sortable, connectWith code, but I also wanted them to both just be set to the larger of the two. To do this I found that you can modify the padding on the lists, and that area will still be an interactable area for purposes of drag-and-drop.
So, to make two connectWith, sortable lists keep the same height, you can add the following handler for the over event:
over: function(event, ui) {
var heightDiff = $("#sourceItems").height() - $("#targetItems").height();
$("#sourceItems").css('padding-bottom', (Math.abs(heightDiff) - heightDiff) / 2 + 'px');
$("#targetItems").css('padding-bottom', (Math.abs(heightDiff) + heightDiff) / 2 + 'px');
}
Here's a fiddler example extending the other example with this event handler: http://jsfiddle.net/TLrn7/
Edit:
$(document).ready(function(){
$("#targetItems").height($("#sourceItems").height());
$("#sourceItems").height($("#sourceItems").height());
});
http://jsfiddle.net/JEY4U/1/
Old Answer:
Use a 'helper' function, which makes sure the dragged elements have proper width and height.
Something like this:
helper: function(event, ui) {
$(ui).width($(ui).width());
$(ui).height($(ui).height());
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
}
You use it like this:
$(SOME_OBJECT).sortable({
connectWith: ...,
placeholder: ...,
......
helper: function....
});
Of course you can write any costume helper function you'd like.
The jQuery UI list height is set to a specific height using CSS. Example for 300px height.
.ui-autocomplete {
max-height: 300px;
overflow-y: auto;
/* prevent horizontal scrollbar */
overflow-x: hidden;
}
/* IE 6 doesn't support max-height
* we use height instead, but this forces the menu to always be this tall
*/
* html .ui-autocomplete {
height: 300px;
}
Read the documentation here: https://jqueryui.com/autocomplete/#maxheight

webkit-transform issue on safari using select elements

I am developing a webapp for ipad and have come across an issue using select option elements when moving divs with webkit-transform. Forgive the table layout but I'm trying to replicate the issue in the app as closely as possible.
Click on the green box and the panels move to the left and the select box is fine. Reload the page and click on the red box and the panels move to the left (using webkit-transform) and when you click on the select box, the list is displayed outside of the browser and the container box jumps.
Note that this is not an issue on the latest GA chrome builds.
<html>
<head>
<title>Select Testing</title>
<style>
.button {
position: relative;
width: 44px;
height: 44px;
}
#moveGood {
background-color: lime;
}
#moveBad {
background-color: red;
}
div#panels {
position: relative;
height: 100%
}
div.panel {
position: relative;
top: 0px;
left: 0px;
width: 200px;
height: 50px;
border: 2px solid black;
}
.leftBad {
-webkit-transform: translate3d(-200px, 0, 0);
}
.leftGood {
left: -200px;
}
div#panelContainer {
position: absolute;
top: 100px;
left: 0;
overflow: hidden;
width: 210px;
}
</style>
<script type="text/javascript">
function leftBad() {
document.getElementById("panels").className += ' leftBad';
}
function leftGood() {
document.getElementById("panels").className += ' leftGood';
}
</script>
</head>
<body>
<div id="moveBad" class="button" onclick="leftBad();"></div>
<div id="moveGood" class="button" onclick="leftGood()";></div>
<div id="panelContainer">
<div id="panels">
<table>
<tr>
<td>
<div id="page1" class="panel">
</div>
</td>
<td>
<div id="page2" class="panel">
<select>
<option value="volvo">
Volvo
</option>
<option value="saab">
Saab
</option>
<option value="mercedes">
Mercedes
</option>
<option value="audi">
Audi
</option>
</select>
</div>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
Safari tries to be helpful when there's a select box partially out of view, if you see:
http://jsfiddle.net/H5J27/
The first example doesn't have -webkit-transform, but when you click on it, it will be displaced in order to reveal it fully.
Now, Safari apparently isn't aware that, once transformed, the select box is in full view. The engine still thinks it's partially obstructed and it will move the select box and it's parent container to a point where it thinks you can see it.
The workarounds are not very encouraging. I'm guessing you're doing this coupled with animation in order to enjoy the benefits of hardware acceleration, so I'd add an event listener and the end of the animation, remove the css transform and apply normal positioning. This will get complicated if you have to do it on several elements, but it's good enough for a one time thing.