Openlayers draw button - button

This example shows a drawing feature upon a button press. It allows you to select different shapes such as points, lines, polygons, etc. I want to incorporate similar functions into my project. But I don't want to select shapes, instead, I want to press the button to turn on the functions of drawing points, lines, polygons, etc.
I assume that button elements should be inserted in the HTML section.
<select id="type">
<option value="Point">Point</option>
<option value="LineString">LineString</option>
<option value="Polygon">Polygon</option>
<option value="Circle">Circle</option>
<option value="None">None</option>
</select>
I tried as below.
</div>
<div id="type">
<button value="Point">button1</button>
<button value="Polygon">button2</button>
<button value="LineString">button3</button>
</div>
It seems to me that something needs to change in the script as well.
var typeSelect = document.getElementById('type');
var draw; // global so we can remove it later
function addInteraction() {
var value = typeSelect.value;
if (value !== 'None') {
draw = new Draw({
source: source,
type: typeSelect.value,
});
map.addInteraction(draw);
}
}
Can somebody please help me?

Change the select to buttons.
<div id="type">
<button id="Point" value="Point">Point</button>
<button id="Polygon" value="Polygon">Polygon</button>
<button id="LineString" value="LineString">LineString</button>
<button id="None" value="None">None</button>
</div>
Add a click listener to each button to set the interaction appropriately
/**
* Handle button clicks.
*/
function handleBtnClick() {
var element=this;
map.removeInteraction(draw);
addInteraction(element);
};
document.getElementById("Point").addEventListener('click', handleBtnClick);
document.getElementById("Polygon").addEventListener('click', handleBtnClick);
document.getElementById("LineString").addEventListener('click', handleBtnClick);
document.getElementById("None").addEventListener('click', handleBtnClick);
working example
code snippet:
var raster = new ol.layer.Tile({ // TileLayer({
source: new ol.source.OSM(),
});
var source = new ol.source.Vector({ // VectorSource({
wrapX: false
});
var vector = new ol.layer.Vector({ // VectorLayer({
source: source,
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4,
}),
});
var typeSelect = document.getElementById('type');
var draw; // global so we can remove it later
function addInteraction(element) {
var value = element.value;
if (value !== 'None') {
draw = new ol.interaction.Draw({
source: source,
type: value,
});
map.addInteraction(draw);
}
}
/**
* Handle button clicks.
*/
function handleBtnClick() {
var element = this;
map.removeInteraction(draw);
addInteraction(element);
// return false;
};
document.getElementById("Point").addEventListener('click', handleBtnClick);
document.getElementById("Polygon").addEventListener('click', handleBtnClick);
document.getElementById("LineString").addEventListener('click', handleBtnClick);
document.getElementById("None").addEventListener('click', handleBtnClick);
addInteraction(document.getElementById('None'));
html,
body {
height: 100%;
width: 100%;
padding: 0px;
margin: 0px;
}
.map {
height: 90%;
width: 100%;
}
<title>Draw Features</title>
<link rel="stylesheet" href="https://openlayers.org/en/v6.4.3/css/ol.css" type="text/css">
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.4.3/build/ol.js"></script>
<div id="map" class="map"></div>
<label>Geometry type </label>
<div id="type">
<button id="Point" value="Point">Point</button>
<button id="Polygon" value="Polygon">Polygon</button>
<button id="LineString" value="LineString">LineString</button>
<button id="None" value="None">None</button>
</div>

Related

Magnific-popup gallery duplicate images when i use it with Owl-carousel

i have developed aspx page
on it i have image galley using owl-carousel
now when i added magnific-popup plugin and used gallery option
then i noticed when i click on image on carousel it get popup successfully but images get duplicated (inside popup)
Owl-Carousel gallery
First popup
Duplicated Image
my aspx code :
<div class="owl-carousel">
<asp:ListView runat="server" ID="lvDesrtProgramGallery" ItemType="SharedKernel.Core.Model.ProgramPhoto" SelectMethod="lvDesrtProgramGallery_GetData">
<ItemTemplate>
<div class="item">
<a class="desert-safari-gallery" href="<%# Item.PhotoPath %>">
<img src="<%# Item.MediumPhotoPath %>" alt="" />
<div class="overlay">
<i class="fa fa-search-plus"></i>
</div>
</a>
</div>
</ItemTemplate>
</asp:ListView>
</div>
Js code
$('.desert-safari .owl-carousel').owlCarousel({
items: 3,
dots: false,
nav: true,
loop: true,
margin: 10,
autoplay: true,
navText: ['<i class="fa fa-angle-left fa-4x"></i>', '<i class="fa fa-angle-right fa-4x"></i>'],
onInitialized: callback,
responsiveClass: true,
responsive: {
0: {
items: 1,
nav: false,
margin: 80
},
570: {
items: 1,
nav: false
},
768: {
items: 2,
nav: false
},
992: {
items: 3,
nav: false,
},
1200: {
items: 3,
nav: true,
loop: false
}
}
});
function callback(event) {
$(".desert-safari-gallery").magnificPopup({
type: "image",
removalDelay: 160,
loop: false,
preloader: false,
fixedContentPos: true,
showCloseBtn: false,
gallery: {
enabled: true
}
})
}
I just ran into this problem so I thought I'd give you my answer/solution.
The Reason:
Since your using owl carousel to loop, owl carousel is cloning items. Because your cloning the items within your carousel you're now feeding duplicates into the popup gallery. What a hassle right? There are two seemingly obvious solutions.
Solution 1: Don't use owl-carousel's loop.
This may not be the preferred solution if you want the looping feature of your carousel but this will no longer cause the popup to receive duplicate entries.
Solution 2: Create an array of objects based on the resulting elements, remove the duplicates, then use magnific's items property to set the gallery items.
Here is a working script I had to create based off a similar scenario I'm sure you can dissect what the process is:
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.gallery img').each(function(i){
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('gallery').magnificPopup({
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
});
}
});
})( jQuery );
I found that #Chris Stage's answer works perfectly, but for some n00bs who try to use the code verbatim may run into issues. I can't just leave a comment or accept the answer so I am posting my revision in hopes that it provides someone else with the correct code.
The one issue I found was that in the .each() function, that you have to target the wrapping a tag's URL to the larger image, not the image's URL itself due to the fact that the one used in the carousel may be a thumbnail or equivalent, and the larger one to the "larger image" to open in a popup may be a separate URL.
(function( $ ) {
'use strict';
$( window ).load(function(){
var GalleryItems = [];
$('.photo-gallery .item a').each(function(i){ //Target your wrapping a tag
var src = $(this).attr('href');
var theSrc = {
src: src,
type: 'image'
};
GalleryItems.push(theSrc);
});
var GalleryItems = GalleryItems.reduce(function(previous, current) {
var object = previous.filter(object => object.src === current.src);
if (object.length == 0) {
previous.push(current);
}
return previous;
}, []);
theGallery();
function theGallery(){
$('.photo-gallery').magnificPopup({ //Target parent carousel container
type: 'image',
gallery: {
enabled:true
},
items:GalleryItems,
removalDelay: 300,
mainClass: 'mfp-fade' //Adds magnific's fade effect
});
}
});
})( jQuery );
This solution worked perfectly with Owl's issue with "cloned" images and thanks to #Chris Stage for coming up with this. His answer should be the "Accepted Answer" but I'd also love an Upvote for the clarification so I can earn some Rep points :)
For future reference, here is a much simpeler solution:
$('.owl-item:not(.cloned) * .desert-safari-gallery').magnificPopup(..
Change your selector so that it will not be used for children of elements with the 'owl-item cloned' class.
You can use this little fix.
$('.owl-carousel.with-mfp').each(function () {
var $mfp = $(this);
$mfp.on('click', '.owl-item.cloned a', function (event) {
event.preventDefault();
var self = $(this);
// Dependency on image positions in owl and on unique a.href attrs
$mfp.find('.owl-item:not(.cloned) a').each(function (index) {
if ($(this).attr('href') === self.attr('href')) {
$mfp.magnificPopup('open', index);
}
});
});
$mfp.magnificPopup({
type: 'image',
delegate: '.owl-item:not(.cloned) a',
gallery: {
enabled: true
}
});

How to run different version of bootstrap in an angular application?

Let's assume i have a previous loaded bootstrap versione , and that i have an angular directive that load some bunch of css (including another version of bootstrap) that i want to use only in a div, or in other tag at my choiche (mostly the ones in which i use the directive).
.directive('directivename' , ['$ocLazyLoad',function($ocLazyLoad){
return {
restrict : 'A',
controller : function($ocLazyLoad,$scope,$q) {
$ocLazyLoad.load('http://somepath/bootstrap/css/bootstrap.css',{cache: false}).then(function(response) {
$ocLazyLoad.load('http://somepath/bootstrap/js/bootstrap.min.js',{cache: false}).then(function(response) { });
});
}
}
}])
and apply it like this, in the way that those css and js only works for that div :
<div class="row" directivename></div>
How can i handle this in angularJS?
Proof of concept, using the JavaScript library thomaspark/scoper
var app = angular.module('MyApp', [], function() {});
app.controller('MyCtrl', function($scope) {});
app.directive('scopedcss', function($http, $compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
// Fetch bootstrap css (you should cache it instead of requesting it everytime)
$http({
method: 'GET',
url: 'https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css'
}).then(function successCallback(response) {
// Create a <style scoped> tag with the CSS content
var cssTag = angular.element('<style scoped>' + response.data + '</style>');
// Insert the tag inside the element
element.prepend(cssTag);
// Call the process() method defined by scoper lib
// It will parse the CSS and prefix it with a unique ID
// It will also add the same ID to the element
window.process();
});
}
}
});
h1 {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.rawgit.com/thomaspark/scoper/29c01744/scoper.min.js"></script>
<div ng-app="MyApp" ng-controller="MyCtrl">
<div scopedcss>
<h1>Hello bootstrap!</h1>
<button type="button" class="btn btn-default">Button</button>
</div>
<h1>Regular title</h1>
<button type="button" class="btn btn-default">Button</button>
</div>

Problems with React-Bootstrap button

This is what i'm trying to do https://react-bootstrap.github.io/components.html#btn-groups but when I click on one of the buttons I want another function to be called
<ButtonGroup>
<Button onClick = {this.onSubmit.bind(this,1)} key={1} active = {this.state.i == 1}>LEFT</Button>
<Button onClick = {this.onSubmit.bind(this,2)} key={2} active = {this.state.i == 2}>MIDDLE</Button>
<Button onClick = {this.onSubmit.bind(this,3)} key={3} active = {this.state.i == 3}>RIGHT</Button>
</ButtonGroup>
onSubmit(new_i: number) {
this.setState({
i: new_i
});
}
I want only one button to be active at a time, the one I click on.
The default value of i is 1. So when I start the program the LEFT button is active and the 2 others are not, which is what I want. But after I cannot click on the other buttons because the value is always 1. And finally my question is how can I change the value on I only the I click on a button.
I would suggest if you're trying to make a item active by changing it CSS or adding a CSS class showing it's active you do something like so, this is a basic example showing that a style is being applied to an element based on the state of i.
https://jsfiddle.net/chrshawkes/64eef3xm/
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
var Hello = React.createClass({
getInitialState: function () {
return { i: 1 }
},
onSubmit: function (value) {
this.setState({ i: value })
},
render: function() {
return (
<div>
<div onClick = {this.onSubmit.bind(this,1)} key={1} style = {this.state.i == 1 ? {color: "red"} : {color: "blue"}}>LEFT</div>
<div onClick = {this.onSubmit.bind(this,2)} key={2} style = {this.state.i == 2 ? {color: "red"} : {color: "blue"}}>MIDDLE</div>
<div onClick = {this.onSubmit.bind(this,3)} key={3} style = {this.state.i == 3 ? {color: "red"} : {color: "blue"}}>RIGHT</div>
</div>
)
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);

problems using meteor to view things on firefox

Hy guys, i'm studing the meteorjs and i got some problems to see the things on firefox. On google chrome, everythings gonna well and i can see everything without errors.
My code is:
/-->server/server.js
Meteor.publish('places', function () {
return Places.find();
});
/-->model.js
Places = new Meteor.Collection('placesNew');
Places.allow({
insert: function(){
return false;
},
update: function(){
return false;
},
remove: function(){
return false;
}
});
Meteor.methods({
createPlace: function(options){
check(options, {name: NonEmptyString, latitude: NonEmptyString , longitude:NonEmptyString , color: NonEmptyString});
return Places.insert({name:options.name, latitude: options.latitude, longitude: options.longitude, color: options.color});
},
removePlace: function(options){
return Places.remove(options.id);
}
});
var NonEmptyString = Match.Where(function (x) {
check(x, String);
return x.length !== 0;
});
/-->services.js
var map;
renderize_map = function (places){
var mapOptions = {
center: new google.maps.LatLng(47.36865 , 8.539183),
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map= new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
places.forEach(function (place) {
var pinColor = place.color.replace("#","");
var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
var marker = new google.maps.Marker({
position: new google.maps.LatLng(place.latitude, place.longitude),
title: place.name,
icon: pinImage,
map: map
});
});
}
/-->client/places_list.js
Meteor.subscribe('places');
Template.places_list.places = function () {
return Places.find({},{sort:{name: -1}});
}
Template.places_list.events({
'click #add':function() {
options ={};
options.name = document.getElementById('name').value;
options.latitude = document.getElementById('latitude').value;
options.longitude = document.getElementById('longitude').value;
options.color = document.getElementById('color').value;
Meteor.call('createPlace',options, function(error,place){
if(error){
console.log("Não Foi possível inserir");
}
});
renderize_map(Places.find({},{sort:{name: 1}}));
},
'click .plc_remove': function(obj){
options={};
options.id=obj.toElement.attributes['data-ref'].value;
Meteor.call('removePlace',options, function(error,place){
if(error){
console.log("Não Foi possível inserir");
}
});
renderize_map(Places.find({},{sort:{name: 1}}));
}
});
Template.maps.rendered = function() {
renderize_map(Places.find({},{sort:{name: 1}}));
}
/-->client/places_list.css
/* CSS declarations go here */
#map-canvas{
width: 500px;
height: 500px;
}
/-->client/places_list.html
<head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"> </script>
</head>
<body>
<header>
<h1>TableList</h1>
{{> places_list}}
{{> maps}}
</header>
</body>
<template name="places_list">
<div class"place-list-form">
<input type="text" placeholder="Insert a place here" value="{{name}}" id="name"/><br>
<input type="text" placeholder="Insert a Latitude here" value="{{latitude}}" id="latitude"/><br>
<input type="text" placeholder="Insert a Longitude here " value="{{longitude}}" id="longitude"/><br>
<input type="text" placeholder="Insert a Color here " value="{{longitude}}" id="color"/>
<button id="add">Add point</button>
</div>
<div class"place-list-container">
<ul>
{{#each places}}
<li> {{ name}} | <a class="plc_remove" data-ref="{{_id}}" href="#">x</a> | </li>
{{/each}}
</ul>
</div>
</template>
<template name="maps">
<div id="map-canvas"></div>
</template>
The errors are:
SyntaxError: missing } after function body
http://localhost:3000/packages/livedata.js?a3d111217f95d5af907302198a85413d1acbaf05
Line 1766
TypeError: Package.livedata is undefined
http://localhost:3000/packages/mongo-livedata.js?a3509c5f9f4ed6ded19eaac97c69c2a91d81df81
Line 28
TypeError: Package.livedata is undefined
http://localhost:3000/packages/global-imports.js?fbb54e05f02190869755c48bbc5e3bd9f17811b4
Line 7
ReferenceError: Template is not defined
http://localhost:3000/client/template.places_list.js?ee7af8e7be9b55207b7bef609fa51cb0e5f513a9
Line 1
TypeError: Meteor.subscribe is not a function
http://localhost:3000/client/places_list.js?6a2a131bfee6da3c6e08cee25711a90317cb4a4e
Line 1
TypeError: Meteor.Collection is not a constructor
http://localhost:3000/model.js?9eed9b90a309156348195efef61705bab5494768
Line 1
ReferenceError: Spark is not defined
http://localhost:3000/client/template.places_list.js?ee7af8e7be9b55207b7bef609fa51cb0e5f513a9
Line 1
Can anyone helpme?
Thanks!
I just copy and pasted all your code into a project and it works for me on both Firefox (version 19.0.2 on OSX) and Chrome. Or at the very least it loads everything and I could add a location that would be visible as a name in the other browser, it didn't add a pin to the map.
The errors you are getting are pretty fundamental errors suggesting that some of the essential built-in packages aren't loading correctly. I don't see why this would only be an issue in one browser though. If you view source in your browser is the list of packages the same in both Chrome and Firefox?
As a suggestion I would try editing the packages file (.meteor/packages from your project root directory). Try removing all the packages which will obviously cause the app to stop working and adding the default ones again which are:
standard-app-packages
autopublish
insecure
preserve-inputs
Beyond that, do other meteor apps run ok in Firefox? If not look at what add-ons and settings you have. If it's just this app and other people can get it working in Firefox then all I can think of is remaking the project copying and pasting your files in.

FusionTablesLayer hides the underlying map on a WordPress page

I'd like to display a Google Map overlaid with two Fusion Tables layers. The code below works perfectly if I just copy it into a text editor, save the file as map.html, and open it in my browser. But when I put it in a post on my WordPress-themed site, the underlying map is hidden by the Fusion Tables layers. Those layers aren't totally opaque: I can see both of them at the same time. I just cannot see the underlying map.
Whenever I zoom or pan the map, the underlying map appears briefly before the Fusion Tables layers are drawn over it. I suspect that there is a style setting at fault. Do you know how to get the map to display properly?
I'm using WordPress version 3.0.4 with the Gazette theme by woothemes; the site is http://www.wisconsinwatch.org.
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
 
<div id="gmap" style="width:590px; padding-top:40px;height: 550px;">
<script type="text/javascript">
var fracmap = new google.maps.Map(document.getElementById('gmap'), {
center: new google.maps.LatLng(44.797709533120106, -90.43712582444374),
zoom: 7,
mapTypeId: 'hybrid'
});
var layer0 = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: 2695847
},
});
layer0.setMap(fracmap);
var layer1 = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: 2695779
},
});
layer1.setMap(fracmap);
</script>
</div>
Thanks!
Wordpress wraps the content of your post in a <div class="entry"> block, which your theme uses to provide the proper styling. Since the javascript that prepares the Google map for display returns an image, the relevant part of the Gazette style sheet is:
.entry img {
padding: 4px;
border: 1px solid #dddddd;
background-color: #FFFFFF;
}
Specifically, the background-color setting causes the overlaid Fusion Tables layers to be drawn with an opaque background, which then hides the underlying map. You need to define a new class in your style sheet (let's call it "map") that draws images with a transparent background:
.map img {
background-color: transparent;
}
And then wrap your javascript in a <div class="map"> block, like so:
<div class="map">
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<div id="gmap" style="width:590px; padding-top:40px;height: 550px;">
<script type="text/javascript">
var fracmap = new google.maps.Map(document.getElementById('gmap'),
center: new google.maps.LatLng(44.797709533120106, -90.43712582444374),
zoom: 7,
mapTypeId: 'hybrid'
});
var layer0 = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: 2695847
},
});
layer0.setMap(fracmap);
var layer1 = new google.maps.FusionTablesLayer({
query: {
select: 'geometry',
from: 2695779
},
});
layer1.setMap(fracmap);
</script>
</div>
</div>

Resources