Giter Site home page Giter Site logo

ui-map's Introduction

UI.Map Build Status

This directive allows you to add Google Maps Javascript API elements.

Requirements

Usage

You can get it from Bower

bower install angular-ui-map

This will copy the UI.Map files into a bower_components folder, along with its dependencies. Load the script files in your application:

<script type="text/javascript" src="bower_components/angular/angular.js"></script>
<script type="text/javascript" src="bower_components/angular-ui-event/dist/event.min.js"></script>
<script type="text/javascript" src="bower_components/angular-ui-map/src/map.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=onGoogleReady"></script>

Make sure to listen to the callback parameter when loading the Google Maps API ! The API must be fully loaded before this module ! Here we name this callback onGoogleReady. To load your angular app after the Google Maps API you can start it with angular.bootstrap.

function onGoogleReady() {
  angular.bootstrap(document.getElementById("map"), ['app.ui-map']);
}

Add the UI.Map module as a dependency to your application module :

var myAppModule = angular.module('app.ui-map', ['ui.map']);

Finally, add the directive to your html:

<section id="map" ng-controller="MapCtrl" >
  <div ui-map="myMap" ui-options="mapOptions" class="map-canvas"></div>
</section>

Note that myMap will be a google.maps.Map class, and mapOptions a google.maps.MapOptions object (see below).

To see something it's better to add some CSS, like

.map-canvas { height: 400px; }

Options

google.maps.MapOptions object can be passed through the main directive attributeui-map.

myAppModule.controller('MapCtrl', ['$scope', function ($scope) {
    $scope.mapOptions = {
      center: new google.maps.LatLng(35.784, -78.670),
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
  }]);

UI.Event

UI.Event allows you to specify custom behavior over user events. You just need to prefix the official event by map- to bind a callback to it.

For example, the click or zoom_changed event of the google.maps.Map class can be used through the UI.Event object keys map-click and map-zoom_changed :

<section id="map" ng-controller="MapCtrl" >
  <div  ui-map="myMap"ui-options="mapOptions" class="map-canvas"
        ui-event="{'map-click': 'addMarker($event, $params)', 'map-zoom_changed': 'setZoomMessage(myMap.getZoom())' }"
  ></div>
</section>

Testing

We use Karma and jshint to ensure the quality of the code. The easiest way to run these checks is to use grunt:

npm install -g grunt-cli
npm install && bower install
grunt

The karma task will try to open Firefox and Chrome as browser in which to run the tests. Make sure this is available or change the configuration in test\karma.conf.js

Grunt Serve

We have one task to serve them all !

grunt serve

It's equal to run separately:

  • grunt connect:server : giving you a development server at http://127.0.0.1:8000/.

  • grunt karma:server : giving you a Karma server to run tests (at http://localhost:9876/ by default). You can force a test on this server with grunt karma:unit:run.

  • grunt watch : will automatically test your code and build your demo. You can demo generation with grunt build:gh-pages.

ui-map's People

Contributors

0x-r4bbit avatar ajoslin avatar bignall avatar cymantic avatar dandoyon avatar darthdeus avatar doogd avatar douglasduteil avatar dunckr avatar edwardhotchkiss avatar facuferrari avatar glebm avatar hllau avatar ivor avatar jmillerdesign avatar joseym avatar joshkurz avatar krohrsb avatar lstrzelecki avatar nateabele avatar peteappleton avatar petebacondarwin avatar phillipj avatar pkozlowski-opensource avatar pracj3am avatar proloser avatar shaungrady avatar sja avatar slav avatar teamon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ui-map's Issues

Custom infoWindow

Hi, and thanks for this module !

Is there a simple way to create a custom info window (I mean without the whole google maps divs) ?

Thanks !

ui-map-marker should create a marker FOR you, instead of merely attach to an existing one.

Kind of annoying if I want to put a few markers onto the page. I think it would be more sensible to do something like this:

<div ui-map>
  <div ng-repeat="marker in markers" ui-map-marker="marker">Popup Html Goes Here</div>
</div>
$scope.markers = [ { position: 11 }, { position: 12 } ];

The 'map' property would be added automatically to the object, and new markers would be generated for you.

ReferenceError: google is not defined

I get the error "ReferenceError: google is not defined" before the function onGoogleReady() is called. I load your module like this:

<script type="text/javascript" src="bower_components/angular-ui-utils/modules/event/event.js "></script>
<script type="text/javascript" src="bower_components/angular-ui-map/src/map.js"></script>
<script src="${pageContext.request.contextPath}/web/views/js/mapController.js"></script>
<script type="text/javascript" charset="utf-8" async="async" src="http://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=onGoogleReady"></script>

If I do not use the attribute async when loading the GoogleAPI I get:

Uncaught TypeError: Cannot call method 'appendChild' of null 

which is called in the line

document.body.appendChild(s);

of Google's js-script.

If I take the following Google-API-script:

<script type="text/javascript" charset="utf-8" src="http://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

and the controller

var myMapsApp = angular.module('myMapsApp', [ 'restangular', 'ui.map', 'ui.event' ]);

function onGoogleReady() {
    console.log('onGoogleReady...');

    //angular.bootstrap(document.getElementById("map"), [ 'app.ui-map' ]);
}

angular.module('myMapsApp').controller('MapController', [ '$scope', function($scope) {
    
    $scope.mapOptions = {
        center : new google.maps.LatLng(35.784, -78.670),
        zoom : 15,
        mapTypeId : google.maps.MapTypeId.ROADMAP
    };
} ]);

... then the maps is displayed but I don't have a callback function registered. Is there any demo-page I could use to solve this?

Support for drawing tools

I have been using ui-map a lot so far, but now wanted to go a step further, and support polygon or rectangle drawing for arbitrary selections on the map. I copied code from this example:

https://developers.google.com/maps/documentation/javascript/examples/drawing-tools

That roughly works as expected, but I am not sure how to attach to the overlaycomplete event. Adding map-overlaycomplete to the ui-events attribute doesn't seem to do the trick, nor adding it inside the directives. Looks like it is an event on the drawingmanager, not on the map.

I would love to see DrawingManager to get integrated into this directive, with support of at least that overlaycomplete event..

map-event binder not taking arguments

When I try to place markers it returns me Cannot read property latLng of undefined.

<div ng-repeat="marker in myMarkers" 
     ui-map-marker="myMarkers[$index]"
     ui-event="{'map-click': 'markerClicked(marker)'}">
</div>

//Module
angular.module('Maptesting', ['ui.map', 'ui.event'])
.controller('CtrlGMap', ['$scope', function($scope) {

    $scope.mapOptions = {
        center: new google.maps.LatLng(-54.798112, -68.303375),
        zoom: 11,
        mapTypeId: google.maps.MapTypeId.SATELLITE
    };

    $scope.myMarkers = [];


    $scope.addMarker = function ($event, $params) {
        $scope.myMarkers.push(new google.maps.Markers({
            map: $scope.myMap,
            position: $params.latLng
        }));
    };

    $scope.markerClicked = function(m) {
        window.alert("clicked");
    };


}]);

angular ui-map, set map to fit markers bounds

I am using ui-map to create a map. I have several points now and I want the map to automatically set the center and the zoom to display all the markers at the beginning.

I found a possible solution here so I added to my project.

The problem is that every time I move around the map, the map goes to the initial zoom and extent.

Is it because angular is continually evaluating the $scope.mapOptions and centering the map?

Controller

$scope.myMarkers = [new google.maps.LatLng (52.537,-2.061), 
                     new google.maps.LatLng (52.564,-2.017)]; 

var latlngbounds = new google.maps.LatLngBounds();


$scope.myMarkers.forEach(function(marker){
               latlngbounds.extend(marker.position);
            });

   $scope.mapOptions = {
        zoom: 17,
        center: latlngbounds.getCenter(),
        mapTypeId: google.maps.MapTypeId.SATELLITE
    };

HTML

             <div id="map_canvas" ui-map="myMap" ui-options="mapOptions" style="height:800px"></div>


            <!--In addition to creating the markers on the map, div elements with existing google.maps.Marker object should be created to hook up with events -->
            <div ng-repeat="marker in myMarkers" ui-map-marker="myMarkers[$index]">
            </div>

How can I solve this?

event $params returns an empty array

I have an application set up in this way:

In the HTML, this is set up to call a function on the controller whenever a click event is triggered on the map:

<div id="map" ui-map="map" ui-options="mapOptions" ui-event="{'map-click': 'mapClick($event, $params)' }"></div>

Inside a controller, I have this:

$scope.mapClick = function ($event, $params) {

    // I want to get lat / lng from the click event
    // However, $params.latLng is undefined.
    $scope.mapService.clicked.lat = $params.latLng.lat()
    $scope.mapService.clicked.lng = $params.latLng.lng()

    // This returns an empty array [ ]
    console.log($params)
}

$params should be returning the normal Angular click event data, according to what I'm seeing in the examples here. Why would it be an empty array? I'm using Angular 1.1.5, if that makes a difference.

update map location (help)

im using an API call to load in person detail. I want to update the map center location once the details are returned from the api but i cant seem to get it to work.

Lead.get($state.params, function(data) {
$scope.lead = data;
$scope.mapOptions.center = new google.maps.LatLng(20.6700, -43.9400);
});

I had already defined mapOptions within the controller scope and just trying to update the LatLng center but no luck. Any suggestions would be great!

Rewrite

Can I just get a quick show of hands on people who are, like, super-invested in the current implementation of this library? Would anybody's feelings be hurt if I submitted a PR with a complete rewrite? The problems as I see them:

This library is pretty un-Angular

  • While I appreciate the idea behind making the GMaps API's native object front-and-center, one thing Angular emphasizes is not imposing on your domain model (hence why 'model' in Angular === $scope). Having access to these objects is nice, but they absolutely should not be forced in front of my face.
  • Way too imperative: there's a lot of low-hanging fruit in terms of functionality that I should be able to implement with an attribute. See: Angular Google Maps: the code might be an atrocity, but at least they nail the simplicity for common use cases.
  • Untestable: relies on global variables exposed by the GMaps API. This is a no-no.
  • Poorly abstracted: I should be able to write adapters for Leaflet or OSM. I can't.

I could go on, and I'll grant that I'm obsessively perfectionistic, but hey, you gotta start somewhere. Thoughts and feedback are welcome. /cc @ProLoser

google is not defined

hi am using google maps in my application its working fine when i run it locally but when i run it on server its giving me the following error.

maperror

help me to solve this problem
thanks in advance

Memory leak in directives for some use cases

The bindMapEvents()-function attaches events to google-maps objects, but it does not handle unbinding when objects are removed (or replaced).

The following use case will cause a memory leak each time setProject() is called.

var markers = {
    "firtProject": [/* list of  Google Maps markers */],
    "secondProject": [/* list of Google Maps markers */]
};
$scope.setProject = function(project) {
    $scope.markers = markers[project];
};
$scope.markerClicked = function(marker) {
    /* some action */
};
<button ng-click="setProject('firstProject')">Project 1</button>
<button ng-click="setProject('secondProject')">Project 2</button>
<div ng-repeat="marker in markers" ui-map-marker="markers[$index]" ui-event="{'map-click': 'markerClicked(marker)'}"></div>

Directive should store unbind markers when they are removed from scope.

Add demo

function MapCtrl($scope) {
    $scope.myMarkers = [];

    $scope.mapOptions = {
        center: new google.maps.LatLng(35.784, -78.670),
        zoom: 15,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    $scope.addMarker = function($event) {
        $scope.myMarkers.push(new google.maps.Marker({
            map: $scope.myMap,
            position: $event.latLng
        }));
    };

    $scope.setZoomMessage = function(zoom) {
        $scope.zoomMessage = 'You just zoomed to '+zoom+'!';
        console.log(zoom,'zoomed');
    };

    $scope.openMarkerInfo = function(marker) {
        $scope.currentMarker = marker;
        $scope.currentMarkerLat = marker.getPosition().lat();
        $scope.currentMarkerLng = marker.getPosition().lng();
        $scope.myInfoWindow.open($scope.myMap, marker);
    };

    $scope.setMarkerPosition = function(marker, lat, lng) {
        marker.setPosition(new google.maps.LatLng(lat, lng));
    };
}
<section id="directives-map" ng-controller="MapCtrl">
                <div class="page-header">
                    <h1>Google Maps</h1>
                </div>
                <div class="well">
                    <div class="row">
                        <div class="span3">
                            <h4>Click to add a marker!</h4>
                            <p>{{zoomMessage}}</p>
                            <ul>
                                <li ng-repeat="marker in myMarkers">
                                    <a class="btn" ng-click="myMap.panTo(marker.getPosition())">
                                        Pan to Marker {{$index}}
                                    </a>
                                </li>
                            </ul>

                            <!-- this is the confusing part. we have to point the map marker directive
                                at an existing google.maps.Marker object, so it can hook up events -->
                            <div ng-repeat="marker in myMarkers" ui-map-marker="myMarkers[$index]"
                                ui-event="{'map-click': 'openMarkerInfo(marker)'}">
                            </div>

                            <div ui-map-info-window="myInfoWindow">
                                <h1>Marker</h1>
                                Lat: <input ng-model="currentMarkerLat">, Lng: <input ng-model="currentMarkerLng">
                                <a class="btn btn-primary" ng-click="setMarkerPosition(currentMarker, currentMarkerLat, currentMarkerLng)">Set Position</a>
                            </div>
                        </div>

                        <!--Giving the div an id="map_canvas" fix problems with twitter bootstrap affecting
                        google maps-->
                        <div id="map_canvas" ui-map="myMap" class="span8 map"
                            ui-event="{'map-click': 'addMarker($event)', 'map-zoom_changed': 'setZoomMessage(myMap.getZoom())' }"
                            ui-options="mapOptions">
                        </div>
                    </div>
                </div>
                <h3>How?</h3>
                <p class="alert alert-info"><i class="icon-info-sign"></i> Remember that you can pass a variable containing an object to <code>ui-event</code></p>
<pre class="prettyprint linenums" ng-non-bindable>
&lt;h4&gt;Click to add a marker!&lt;/h4&gt;
&lt;p&gt;{{zoomMessage}}&lt;/p&gt;
&lt;ul&gt;
  &lt;li ng-repeat=&quot;marker in myMarkers&quot;&gt;
    &lt;a ng-click=&quot;myMap.panTo(marker.getPosition())&quot;&gt;Pan to Marker {{$index}}&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- this is the confusing part. we have to point the map marker directive
  at an existing google.maps.Marker object, so it can hook up events --&gt;
&lt;div ng-repeat=&quot;marker in myMarkers&quot; ui-map-marker=&quot;myMarkers[$index]&quot;
  ui-event=&quot;{&#x27;map-click&#x27;: &#x27;openMarkerInfo(marker)&#x27;}&quot;&gt;
&lt;/div&gt;

&lt;div ui-map-info-window=&quot;myInfoWindow&quot;&gt;
  &lt;h1&gt;Marker&lt;/h1&gt;
  Lat: &lt;input ng-model=&quot;currentMarkerLat&quot;&gt;, Lng: &lt;input ng-model=&quot;currentMarkerLng&quot;&gt;
  &lt;a ng-click=&quot;setMarkerPosition(currentMarker, currentMarkerLat, currentMarkerLng)&quot;&gt;Set Position&lt;/a&gt;
&lt;/div&gt;

&lt;!-- Giving the div an id="map_canvas" fix problems with twitter bootstrap affecting
google maps --&gt;
&lt;div id=&quot;map_canvas&quot; ui-map=&quot;myMap&quot; class=&quot;map&quot;
  ui-event=&quot;{&#x27;map-click&#x27;: &#x27;addMarker($event)&#x27;, &#x27;map-zoom_changed&#x27;: &#x27;setZoomMessage(myMap.getZoom())&#x27; }&quot;
  ui-options=&quot;mapOptions&quot;&gt;
&lt;/div&gt;

&lt;script&gt;
$scope.myMarkers = [];

$scope.mapOptions = {
  center: new google.maps.LatLng(35.784, -78.670),
  zoom: 15,
  mapTypeId: google.maps.MapTypeId.ROADMAP
};

$scope.addMarker = function($event) {
  $scope.myMarkers.push(new google.maps.Marker({
    map: $scope.myMap,
    position: $event.latLng
  }));
};

$scope.setZoomMessage = function(zoom) {
  $scope.zoomMessage = &#x27;You just zoomed to &#x27;+zoom+&#x27;!&#x27;;
  console.log(zoom,&#x27;zoomed&#x27;)
};

$scope.openMarkerInfo = function(marker) {
  $scope.currentMarker = marker;
  $scope.currentMarkerLat = marker.getPosition().lat();
  $scope.currentMarkerLng = marker.getPosition().lng();
  $scope.myInfoWindow.open($scope.myMap, marker);
};

$scope.setMarkerPosition = function(marker, lat, lng) {
  marker.setPosition(new google.maps.LatLng(lat, lng));
};
&lt;/script&gt;

&lt;style&gt;
.map {
  height: 400px;
  width: 600px;
}
&lt;/style&gt;
</pre>
            </section>

use with ng-if causes map to not attach to scope.

I have a section of the page that is using ng-if to add/remove from the page and that section has a map inside of it. The map will show on the page but it is never placed on the scope so I am unable to interact with it or show Markers on it.

npmjs.com

Hi, could you push this lib to npm?

Because it now possible to download only using bower.

showing ui-map in angular-modal-service shows error

I implemented the ui-map successfully in separate page but now I am implementing it in modal. Map is not shown and when I drag map area this error is shown. Uncaught TypeError: Cannot read property 'x' of undefined. When I click the map area, I get this error. Uncaught RangeError: Maximum call stack size exceeded. The same code was running when using without the modal. I am stuck. Has anyone the solution?

Compatibility issues with Cordova for iOS

When running it on a browser with no 'deviceready' listener there is no issues at all, it works like a charm and is very powerful.

Unfortunately though I am having a few hickups when it comes to Cordova, so after running `grunt build' and doing either 'cordova emulate ios' or 'cordova build ios' loading it directly on my phone it is unable to load the map at all.

My current controller setup looks like this:

// required for UI-Map
function onGoogleReady() {
angular.bootstrap(document.getElementById("map"), ['app.ui-map']);
}

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {

var styles = [
              {
                  "featureType": "all",
                  "elementType": "labels.text.fill",
                  "stylers": [
                      {
                          "saturation": "0"
                      ...
          ];

$scope.mapOptions = {
  styles: styles,
  zoom: 16,
  center: new google.maps.LatLng(37.82670075048411, -122.42281079292297),
  mapTypeControlOptions: {
    mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
  },
  panControl: false,
  zoomControl: false,
  mapTypeControl: false,
  scaleControl: false,
  streetViewControl: false,
  overviewMapControl: false
};

Any help with this would be absolutely awesome.

Thank you.

where to get started? documentation, demo?

Hi all,

The readme seems to be some generic document without containing any details about this ui-maps project. The demo.html contained in the demo directory looks like it needs to be included from some other html file as it does not even include Angular. An online demo at http://douglasduteil.github.io/ui-map/ seems to be not quite working as it should (adding a marker and panning to it does not work.)

All in all I'm lost whether this module is in a usable state at all. Please advice..

Support for tilesloaded?

I need to do geocoding on a map object, and as best I could see, there is no support for "addListenerOnce" and/or the tilesloaded event.

It was trivial to add it. And yes, I know this is NOT elegant. :)

  function bindMapEvents(scope, eventsStr, googleObject, element) {
  // Jason's hack. This makes the "ready" function fire on map load.
      google.maps.event.addListenerOnce(googleObject, 'tilesloaded', function() {
        scope.ready();
      });
    angular.forEach(eventsStr.split(' '), function (eventName) {
     ...
    }
  }

In the controller:

/* ready() is a custom definition that I added to the ui-map code.
   It sets up a one time listener that will run on 'tilesloaded' */
$scope.ready = function() {
    $scope.getCoords($scope.address1 + " " + $scope.city + " " + $scope.selectedState + " " + $scope.zip);
};

Not a show stopper, just an FYI.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.