├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── debug
└── map.html
├── dist
├── Leaflet.Coordinates-0.1.5.css
├── Leaflet.Coordinates-0.1.5.ie.css
├── Leaflet.Coordinates-0.1.5.min.js
└── Leaflet.Coordinates-0.1.5.src.js
├── examples
└── demo.html
├── package.json
├── spec
├── Grunt.Helper.js
├── Number.Formatter.Spec.js
└── SpecRunner.html
└── src
├── Control.Coordinates.css
├── Control.Coordinates.ie.css
├── Control.Coordinates.js
└── util
└── NumberFormatter.js
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | build/
196 | eggs/
197 | parts/
198 | var/
199 | sdist/
200 | develop-eggs/
201 | .installed.cfg
202 |
203 | # Installer logs
204 | pip-log.txt
205 |
206 | # Unit test / coverage reports
207 | .coverage
208 | .tox
209 |
210 | #Translations
211 | *.mo
212 |
213 | #Mr Developer
214 | .mr.developer.cfg
215 |
216 | #Node
217 | node_modules
218 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(grunt) {
4 |
5 | // Project configuration.
6 | grunt.initConfig({
7 | pkg: grunt.file.readJSON('package.json'),
8 | clean: {
9 | all: {
10 | src: ['dist/**/*']
11 | }
12 | },
13 | concat: {
14 | options: {
15 | separator: ''
16 | },
17 | dist: {
18 | src: ['src/**/*.js'],
19 | dest: 'dist/<%= pkg.name%>-<%= pkg.version%>.src.js'
20 | }
21 | },
22 | uglify: {
23 | options: {
24 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
25 | },
26 | dist: {
27 | files: {
28 | 'dist/<%= pkg.name %>-<%= pkg.version%>.min.js': ['<%= concat.dist.dest %>']
29 | }
30 | }
31 | },
32 | cssmin: {
33 | combine: {
34 | files: {
35 | 'dist/<%= pkg.name %>-<%= pkg.version%>.css': ['src/Control.Coordinates.css'],
36 | 'dist/<%= pkg.name %>-<%= pkg.version%>.ie.css': ['src/Control.Coordinates.ie.css']
37 | }
38 | },
39 | minify: {
40 | expand: true,
41 | cwd: 'dist/',
42 | src: ['*.css', '!*.min.css'],
43 | dest: 'dist/'
44 | }
45 | },
46 | csslint: {
47 | strict: {
48 | options: {
49 | import: 2,
50 | 'adjoining-classes': false
51 | },
52 | src: ['src/**/*.css']
53 | }
54 | },
55 | jasmine: {
56 | pivotal: {
57 | src: [
58 | 'src/**/*.js'
59 | ],
60 | options: {
61 | specs: 'spec/*Spec.js',
62 | helpers: 'spec/*Helper.js',
63 | vendor: [
64 | 'http://cdn.leafletjs.com/leaflet-0.5.1/leaflet-src.js'
65 | ],
66 | '--local-to-remote-url-access': true
67 | }
68 | }
69 | },
70 | jshint: {
71 | // define the files to lint
72 | files: ['src/**/*.js'],
73 | // configure JSHint (documented at http://www.jshint.com/docs/)
74 | options: {
75 | // more options here if you want to override JSHint defaults
76 | globals: {
77 | console: true,
78 | module: true
79 | }
80 | }
81 | },
82 | connect: {
83 | server: {
84 | options: {
85 | port: 9001,
86 | base: 'spec'
87 | }
88 | }
89 | }
90 |
91 | });
92 |
93 | grunt.loadNpmTasks('grunt-contrib-uglify');
94 | grunt.loadNpmTasks('grunt-contrib-concat');
95 | grunt.loadNpmTasks('grunt-contrib-clean');
96 | grunt.loadNpmTasks('grunt-contrib-cssmin');
97 | grunt.loadNpmTasks('grunt-contrib-jshint');
98 | grunt.loadNpmTasks('grunt-contrib-csslint');
99 | grunt.loadNpmTasks('grunt-contrib-jasmine');
100 | grunt.loadNpmTasks('grunt-contrib-connect');
101 |
102 | // Default task(s).
103 | grunt.registerTask('default', ['clean', 'jshint', 'connect', 'jasmine', 'csslint', 'concat', 'uglify', 'cssmin']);
104 |
105 | grunt.registerTask('test', ['connect', 'jasmine']);
106 |
107 | };
108 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This work is licensed under a Creative Commons Attribution 3.0 Unported License.
2 | http://creativecommons.org/licenses/by/3.0
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Leaflet.Coordinates
2 | ===================
3 |
4 | ### What is this?
5 | A [Leaflet](https://github.com/Leaflet/Leaflet) plugin to view mouse coordinates. Also the user can change the coordinates and get a marker on that position viewing the coordinates.
6 |
7 | *Tested with Leaflet 0.5+*
8 |
9 |
10 |
11 |
12 |
13 | ### Demo anyone?
14 | [Have a look](http://mrmufflon.github.io/Leaflet.Coordinates/examples/demo.html)
15 |
16 | ### How to use?
17 | ```javascript
18 | L.control.coordinates({
19 | position:"bottomleft", //optional default "bootomright"
20 | decimals:2, //optional default 4
21 | decimalSeperator:".", //optional default "."
22 | labelTemplateLat:"Latitude: {y}", //optional default "Lat: {y}"
23 | labelTemplateLng:"Longitude: {x}", //optional default "Lng: {x}"
24 | enableUserInput:true, //optional default true
25 | useDMS:false, //optional default false
26 | useLatLngOrder: true, //ordering of labels, default false-> lng-lat
27 | markerType: L.marker, //optional default L.marker
28 | markerProps: {}, //optional default {},
29 | labelFormatterLng : function(lng){return lng+" lng"}, //optional default none,
30 | labelFormatterLat : function(lat){return lat+" lat"}, //optional default none
31 | customLabelFcn: function(latLonObj, opts) { "Geohash: " + encodeGeoHash(latLonObj.lat, latLonObj.lng)} //optional default none
32 | }).addTo(map);
33 | ```
34 |
35 | ### Releases
36 | - [0.1.3](https://github.com/MrMufflon/Leaflet.Coordinates/tree/0.1.3)
37 | - [0.1.2](https://github.com/MrMufflon/Leaflet.Coordinates/tree/0.1.2)
38 | - [0.1.1](https://github.com/MrMufflon/Leaflet.Coordinates/tree/0.1.1)
39 | - [0.1.0](https://github.com/MrMufflon/Leaflet.Coordinates/tree/0.1.0)
40 |
41 | ### License
42 | 
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
43 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Leaflet.Coordinates",
3 | "version": "0.1.5",
4 | "homepage": "https://github.com/MrMufflon/Leaflet.Coordinates",
5 | "authors": [
6 | "MrMufflon"
7 | ],
8 | "description": "A Leaflet plugin to view coordinates",
9 | "main": [
10 | "dist/Leaflet.Coordinates-0.1.5.min.js",
11 | "dist/Leaflet.Coordinates-0.1.5.css"
12 | ],
13 | "keywords": [
14 | "Leaflet",
15 | "Coorniates",
16 | "map"
17 | ],
18 | "license": "MIT",
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "tests"
25 | ],
26 | "dependencies": {
27 | "leaflet": "0.7.x"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/debug/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Coordinate viewing test page
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/dist/Leaflet.Coordinates-0.1.5.css:
--------------------------------------------------------------------------------
1 | .leaflet-control-coordinates{background-color:#D8D8D8;background-color:rgba(255,255,255,.8);cursor:pointer}.leaflet-control-coordinates,.leaflet-control-coordinates .uiElement input{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.leaflet-control-coordinates .uiElement{margin:4px}.leaflet-control-coordinates .uiElement .labelFirst{margin-right:4px}.leaflet-control-coordinates .uiHidden{display:none}.leaflet-control-coordinates .uiElement.label{color:inherit;font-weight:inherit;font-size:inherit;padding:0;display:inherit}
--------------------------------------------------------------------------------
/dist/Leaflet.Coordinates-0.1.5.ie.css:
--------------------------------------------------------------------------------
1 | .leaflet-control-coordinates{background-color:#D8D8D8}
--------------------------------------------------------------------------------
/dist/Leaflet.Coordinates-0.1.5.min.js:
--------------------------------------------------------------------------------
1 | /*! leaflet.coordinates 07-12-2016 */
2 | L.Control.Coordinates=L.Control.extend({options:{position:"bottomright",decimals:4,decimalSeperator:".",labelTemplateLat:"Lat: {y}",labelTemplateLng:"Lng: {x}",labelFormatterLat:void 0,labelFormatterLng:void 0,enableUserInput:!0,useDMS:!1,useLatLngOrder:!1,centerUserCoordinates:!1,markerType:L.marker,markerProps:{}},onAdd:function(a){this._map=a;var b="leaflet-control-coordinates",c=this._container=L.DomUtil.create("div",b),d=this.options;this._labelcontainer=L.DomUtil.create("div","uiElement label",c),this._label=L.DomUtil.create("span","labelFirst",this._labelcontainer),this._inputcontainer=L.DomUtil.create("div","uiElement input uiHidden",c);var e,f;return d.useLatLngOrder?(f=L.DomUtil.create("span","",this._inputcontainer),this._inputY=this._createInput("inputY",this._inputcontainer),e=L.DomUtil.create("span","",this._inputcontainer),this._inputX=this._createInput("inputX",this._inputcontainer)):(e=L.DomUtil.create("span","",this._inputcontainer),this._inputX=this._createInput("inputX",this._inputcontainer),f=L.DomUtil.create("span","",this._inputcontainer),this._inputY=this._createInput("inputY",this._inputcontainer)),e.innerHTML=d.labelTemplateLng.replace("{x}",""),f.innerHTML=d.labelTemplateLat.replace("{y}",""),L.DomEvent.on(this._inputX,"keyup",this._handleKeypress,this),L.DomEvent.on(this._inputY,"keyup",this._handleKeypress,this),a.on("mousemove",this._update,this),a.on("dragstart",this.collapse,this),a.whenReady(this._update,this),this._showsCoordinates=!0,d.enableUserInput&&L.DomEvent.addListener(this._container,"click",this._switchUI,this),c},_createInput:function(a,b){var c=L.DomUtil.create("input",a,b);return c.type="text",L.DomEvent.disableClickPropagation(c),c},_clearMarker:function(){this._map.removeLayer(this._marker)},_handleKeypress:function(a){switch(a.keyCode){case 27:this.collapse();break;case 13:this._handleSubmit(),this.collapse();break;default:this._handleSubmit()}},_handleSubmit:function(){var a=L.NumberFormatter.createValidNumber(this._inputX.value,this.options.decimalSeperator),b=L.NumberFormatter.createValidNumber(this._inputY.value,this.options.decimalSeperator);if(void 0!==a&&void 0!==b){var c=this._marker;c||(c=this._marker=this._createNewMarker(),c.on("click",this._clearMarker,this));var d=new L.LatLng(b,a);c.setLatLng(d),c.addTo(this._map),this.options.centerUserCoordinates&&this._map.setView(d,this._map.getZoom())}},expand:function(){this._showsCoordinates=!1,this._map.off("mousemove",this._update,this),L.DomEvent.addListener(this._container,"mousemove",L.DomEvent.stop),L.DomEvent.removeListener(this._container,"click",this._switchUI,this),L.DomUtil.addClass(this._labelcontainer,"uiHidden"),L.DomUtil.removeClass(this._inputcontainer,"uiHidden")},_createCoordinateLabel:function(a){var b,c,d=this.options;return d.customLabelFcn?d.customLabelFcn(a,d):(b=d.labelFormatterLng?d.labelFormatterLng(a.lng):L.Util.template(d.labelTemplateLng,{x:this._getNumber(a.lng,d)}),c=d.labelFormatterLat?d.labelFormatterLat(a.lat):L.Util.template(d.labelTemplateLat,{y:this._getNumber(a.lat,d)}),d.useLatLngOrder?c+" "+b:b+" "+c)},_getNumber:function(a,b){var c;return c=b.useDMS?L.NumberFormatter.toDMS(a):L.NumberFormatter.round(a,b.decimals,b.decimalSeperator)},collapse:function(){if(!this._showsCoordinates){this._map.on("mousemove",this._update,this),this._showsCoordinates=!0;this.options;if(L.DomEvent.addListener(this._container,"click",this._switchUI,this),L.DomEvent.removeListener(this._container,"mousemove",L.DomEvent.stop),L.DomUtil.addClass(this._inputcontainer,"uiHidden"),L.DomUtil.removeClass(this._labelcontainer,"uiHidden"),this._marker){var a=this._createNewMarker(),b=this._marker.getLatLng();a.setLatLng(b);var c=L.DomUtil.create("div",""),d=L.DomUtil.create("div","",c);d.innerHTML=this._ordinateLabel(b);var e=L.DomUtil.create("a","",c);e.innerHTML="Remove",e.href="#";var f=L.DomEvent.stopPropagation;L.DomEvent.on(e,"click",f).on(e,"mousedown",f).on(e,"dblclick",f).on(e,"click",L.DomEvent.preventDefault).on(e,"click",function(){this._map.removeLayer(a)},this),a.bindPopup(c),a.addTo(this._map),this._map.removeLayer(this._marker),this._marker=null}}},_switchUI:function(a){L.DomEvent.stop(a),L.DomEvent.stopPropagation(a),L.DomEvent.preventDefault(a),this._showsCoordinates?this.expand():this.collapse()},onRemove:function(a){a.off("mousemove",this._update,this)},_update:function(a){var b=a.latlng,c=this.options;b&&(b=b.wrap(),this._currentPos=b,this._inputY.value=L.NumberFormatter.round(b.lat,c.decimals,c.decimalSeperator),this._inputX.value=L.NumberFormatter.round(b.lng,c.decimals,c.decimalSeperator),this._label.innerHTML=this._createCoordinateLabel(b))},_createNewMarker:function(){return this.options.markerType(null,this.options.markerProps)}}),L.control.coordinates=function(a){return new L.Control.Coordinates(a)},L.Map.mergeOptions({coordinateControl:!1}),L.Map.addInitHook(function(){this.options.coordinateControl&&(this.coordinateControl=new L.Control.Coordinates,this.addControl(this.coordinateControl))}),L.NumberFormatter={round:function(a,b,c){var d=L.Util.formatNum(a,b)+"",e=d.split(".");if(e[1]){for(var f=b-e[1].length;f>0;f--)e[1]+="0";d=e.join(c||".")}return d},toDMS:function(a){var b=Math.floor(Math.abs(a)),c=60*(Math.abs(a)-b),d=Math.floor(c),e=60*(c-d),f=Math.round(e);60==f&&(d++,f="00"),60==d&&(b++,d="00"),10>f&&(f="0"+f),10>d&&(d="0"+d);var g="";return 0>a&&(g="-"),""+g+b+"° "+d+"' "+f+"''"},createValidNumber:function(a,b){if(a&&a.length>0){var c=a.split(b||".");try{var d=Number(c.join("."));return isNaN(d)?void 0:d}catch(e){return void 0}}return void 0}};
--------------------------------------------------------------------------------
/dist/Leaflet.Coordinates-0.1.5.src.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.Control.Coordinates is used for displaying current mouse coordinates on the map.
3 | */
4 |
5 | L.Control.Coordinates = L.Control.extend({
6 | options: {
7 | position: 'bottomright',
8 | //decimals used if not using DMS or labelFormatter functions
9 | decimals: 4,
10 | //decimalseperator used if not using DMS or labelFormatter functions
11 | decimalSeperator: ".",
12 | //label templates for usage if no labelFormatter function is defined
13 | labelTemplateLat: "Lat: {y}",
14 | labelTemplateLng: "Lng: {x}",
15 | //label formatter functions
16 | labelFormatterLat: undefined,
17 | labelFormatterLng: undefined,
18 | //switch on/off input fields on click
19 | enableUserInput: true,
20 | //use Degree-Minute-Second
21 | useDMS: false,
22 | //if true lat-lng instead of lng-lat label ordering is used
23 | useLatLngOrder: false,
24 | //if true user given coordinates are centered directly
25 | centerUserCoordinates: false,
26 | //leaflet marker type
27 | markerType: L.marker,
28 | //leaflet marker properties
29 | markerProps: {}
30 | },
31 |
32 | onAdd: function(map) {
33 | this._map = map;
34 |
35 | var className = 'leaflet-control-coordinates',
36 | container = this._container = L.DomUtil.create('div', className),
37 | options = this.options;
38 |
39 | //label containers
40 | this._labelcontainer = L.DomUtil.create("div", "uiElement label", container);
41 | this._label = L.DomUtil.create("span", "labelFirst", this._labelcontainer);
42 |
43 |
44 | //input containers
45 | this._inputcontainer = L.DomUtil.create("div", "uiElement input uiHidden", container);
46 | var xSpan, ySpan;
47 | if (options.useLatLngOrder) {
48 | ySpan = L.DomUtil.create("span", "", this._inputcontainer);
49 | this._inputY = this._createInput("inputY", this._inputcontainer);
50 | xSpan = L.DomUtil.create("span", "", this._inputcontainer);
51 | this._inputX = this._createInput("inputX", this._inputcontainer);
52 | } else {
53 | xSpan = L.DomUtil.create("span", "", this._inputcontainer);
54 | this._inputX = this._createInput("inputX", this._inputcontainer);
55 | ySpan = L.DomUtil.create("span", "", this._inputcontainer);
56 | this._inputY = this._createInput("inputY", this._inputcontainer);
57 | }
58 | xSpan.innerHTML = options.labelTemplateLng.replace("{x}", "");
59 | ySpan.innerHTML = options.labelTemplateLat.replace("{y}", "");
60 |
61 | L.DomEvent.on(this._inputX, 'keyup', this._handleKeypress, this);
62 | L.DomEvent.on(this._inputY, 'keyup', this._handleKeypress, this);
63 |
64 | //connect to mouseevents
65 | map.on("mousemove", this._update, this);
66 | map.on('dragstart', this.collapse, this);
67 |
68 | map.whenReady(this._update, this);
69 |
70 | this._showsCoordinates = true;
71 | //wether or not to show inputs on click
72 | if (options.enableUserInput) {
73 | L.DomEvent.addListener(this._container, "click", this._switchUI, this);
74 | }
75 |
76 | return container;
77 | },
78 |
79 | /**
80 | * Creates an input HTML element in given container with given classname
81 | */
82 | _createInput: function(classname, container) {
83 | var input = L.DomUtil.create("input", classname, container);
84 | input.type = "text";
85 | L.DomEvent.disableClickPropagation(input);
86 | return input;
87 | },
88 |
89 | _clearMarker: function() {
90 | this._map.removeLayer(this._marker);
91 | },
92 |
93 | /**
94 | * Called onkeyup of input fields
95 | */
96 | _handleKeypress: function(e) {
97 | switch (e.keyCode) {
98 | case 27: //Esc
99 | this.collapse();
100 | break;
101 | case 13: //Enter
102 | this._handleSubmit();
103 | this.collapse();
104 | break;
105 | default: //All keys
106 | this._handleSubmit();
107 | break;
108 | }
109 | },
110 |
111 | /**
112 | * Called on each keyup except ESC
113 | */
114 | _handleSubmit: function() {
115 | var x = L.NumberFormatter.createValidNumber(this._inputX.value, this.options.decimalSeperator);
116 | var y = L.NumberFormatter.createValidNumber(this._inputY.value, this.options.decimalSeperator);
117 | if (x !== undefined && y !== undefined) {
118 | var marker = this._marker;
119 | if (!marker) {
120 | marker = this._marker = this._createNewMarker();
121 | marker.on("click", this._clearMarker, this);
122 | }
123 | var ll = new L.LatLng(y, x);
124 | marker.setLatLng(ll);
125 | marker.addTo(this._map);
126 | if (this.options.centerUserCoordinates) {
127 | this._map.setView(ll, this._map.getZoom());
128 | }
129 | }
130 | },
131 |
132 | /**
133 | * Shows inputs fields
134 | */
135 | expand: function() {
136 | this._showsCoordinates = false;
137 |
138 | this._map.off("mousemove", this._update, this);
139 |
140 | L.DomEvent.addListener(this._container, "mousemove", L.DomEvent.stop);
141 | L.DomEvent.removeListener(this._container, "click", this._switchUI, this);
142 |
143 | L.DomUtil.addClass(this._labelcontainer, "uiHidden");
144 | L.DomUtil.removeClass(this._inputcontainer, "uiHidden");
145 | },
146 |
147 | /**
148 | * Creates the label according to given options and formatters
149 | */
150 | _createCoordinateLabel: function(ll) {
151 | var opts = this.options,
152 | x, y;
153 | if (opts.customLabelFcn) {
154 | return opts.customLabelFcn(ll, opts);
155 | }
156 | if (opts.labelFormatterLng) {
157 | x = opts.labelFormatterLng(ll.lng);
158 | } else {
159 | x = L.Util.template(opts.labelTemplateLng, {
160 | x: this._getNumber(ll.lng, opts)
161 | });
162 | }
163 | if (opts.labelFormatterLat) {
164 | y = opts.labelFormatterLat(ll.lat);
165 | } else {
166 | y = L.Util.template(opts.labelTemplateLat, {
167 | y: this._getNumber(ll.lat, opts)
168 | });
169 | }
170 | if (opts.useLatLngOrder) {
171 | return y + " " + x;
172 | }
173 | return x + " " + y;
174 | },
175 |
176 | /**
177 | * Returns a Number according to options (DMS or decimal)
178 | */
179 | _getNumber: function(n, opts) {
180 | var res;
181 | if (opts.useDMS) {
182 | res = L.NumberFormatter.toDMS(n);
183 | } else {
184 | res = L.NumberFormatter.round(n, opts.decimals, opts.decimalSeperator);
185 | }
186 | return res;
187 | },
188 |
189 | /**
190 | * Shows coordinate labels after user input has ended. Also
191 | * displays a marker with popup at the last input position.
192 | */
193 | collapse: function() {
194 | if (!this._showsCoordinates) {
195 | this._map.on("mousemove", this._update, this);
196 | this._showsCoordinates = true;
197 | var opts = this.options;
198 | L.DomEvent.addListener(this._container, "click", this._switchUI, this);
199 | L.DomEvent.removeListener(this._container, "mousemove", L.DomEvent.stop);
200 |
201 | L.DomUtil.addClass(this._inputcontainer, "uiHidden");
202 | L.DomUtil.removeClass(this._labelcontainer, "uiHidden");
203 |
204 | if (this._marker) {
205 | var m = this._createNewMarker(),
206 | ll = this._marker.getLatLng();
207 | m.setLatLng(ll);
208 |
209 | var container = L.DomUtil.create("div", "");
210 | var label = L.DomUtil.create("div", "", container);
211 | label.innerHTML = this._ordinateLabel(ll);
212 |
213 | var close = L.DomUtil.create("a", "", container);
214 | close.innerHTML = "Remove";
215 | close.href = "#";
216 | var stop = L.DomEvent.stopPropagation;
217 |
218 | L.DomEvent
219 | .on(close, 'click', stop)
220 | .on(close, 'mousedown', stop)
221 | .on(close, 'dblclick', stop)
222 | .on(close, 'click', L.DomEvent.preventDefault)
223 | .on(close, 'click', function() {
224 | this._map.removeLayer(m);
225 | }, this);
226 |
227 | m.bindPopup(container);
228 | m.addTo(this._map);
229 | this._map.removeLayer(this._marker);
230 | this._marker = null;
231 | }
232 | }
233 | },
234 |
235 | /**
236 | * Click callback for UI
237 | */
238 | _switchUI: function(evt) {
239 | L.DomEvent.stop(evt);
240 | L.DomEvent.stopPropagation(evt);
241 | L.DomEvent.preventDefault(evt);
242 | if (this._showsCoordinates) {
243 | //show textfields
244 | this.expand();
245 | } else {
246 | //show coordinates
247 | this.collapse();
248 | }
249 | },
250 |
251 | onRemove: function(map) {
252 | map.off("mousemove", this._update, this);
253 | },
254 |
255 | /**
256 | * Mousemove callback function updating labels and input elements
257 | */
258 | _update: function(evt) {
259 | var pos = evt.latlng,
260 | opts = this.options;
261 | if (pos) {
262 | pos = pos.wrap();
263 | this._currentPos = pos;
264 | this._inputY.value = L.NumberFormatter.round(pos.lat, opts.decimals, opts.decimalSeperator);
265 | this._inputX.value = L.NumberFormatter.round(pos.lng, opts.decimals, opts.decimalSeperator);
266 | this._label.innerHTML = this._createCoordinateLabel(pos);
267 | }
268 | },
269 |
270 | _createNewMarker: function() {
271 | return this.options.markerType(null, this.options.markerProps);
272 | }
273 |
274 | });
275 |
276 | //constructor registration
277 | L.control.coordinates = function(options) {
278 | return new L.Control.Coordinates(options);
279 | };
280 |
281 | //map init hook
282 | L.Map.mergeOptions({
283 | coordinateControl: false
284 | });
285 |
286 | L.Map.addInitHook(function() {
287 | if (this.options.coordinateControl) {
288 | this.coordinateControl = new L.Control.Coordinates();
289 | this.addControl(this.coordinateControl);
290 | }
291 | });
292 | L.NumberFormatter = {
293 | round: function(num, dec, sep) {
294 | var res = L.Util.formatNum(num, dec) + "",
295 | numbers = res.split(".");
296 | if (numbers[1]) {
297 | var d = dec - numbers[1].length;
298 | for (; d > 0; d--) {
299 | numbers[1] += "0";
300 | }
301 | res = numbers.join(sep || ".");
302 | }
303 | return res;
304 | },
305 |
306 | toDMS: function(deg) {
307 | var d = Math.floor(Math.abs(deg));
308 | var minfloat = (Math.abs(deg) - d) * 60;
309 | var m = Math.floor(minfloat);
310 | var secfloat = (minfloat - m) * 60;
311 | var s = Math.round(secfloat);
312 | if (s == 60) {
313 | m++;
314 | s = "00";
315 | }
316 | if (m == 60) {
317 | d++;
318 | m = "00";
319 | }
320 | if (s < 10) {
321 | s = "0" + s;
322 | }
323 | if (m < 10) {
324 | m = "0" + m;
325 | }
326 | var dir = "";
327 | if (deg < 0) {
328 | dir = "-";
329 | }
330 | return ("" + dir + d + "° " + m + "' " + s + "''");
331 | },
332 |
333 | createValidNumber: function(num, sep) {
334 | if (num && num.length > 0) {
335 | var numbers = num.split(sep || ".");
336 | try {
337 | var numRes = Number(numbers.join("."));
338 | if (isNaN(numRes)) {
339 | return undefined;
340 | }
341 | return numRes;
342 | } catch (e) {
343 | return undefined;
344 | }
345 | }
346 | return undefined;
347 | }
348 | };
--------------------------------------------------------------------------------
/examples/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet.Coordinates Demo Page
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "leaflet.coordinates",
3 | "version": "0.1.5",
4 | "description": "A Leaflet plugin to view coordinates",
5 | "devDependencies": {
6 | "grunt": "~0.4.1",
7 | "grunt-contrib-uglify": "~0.2.2",
8 | "grunt-contrib-concat": "~0.3.0",
9 | "grunt-contrib-clean": "~0.4.1",
10 | "grunt-contrib-cssmin": "~0.6.1",
11 | "grunt-contrib-csslint": "~0.1.2",
12 | "grunt-contrib-jshint": "~0.11.1",
13 | "grunt-contrib-connect": "~0.10",
14 | "grunt-contrib-jasmine": "~0.8",
15 | "jasmine": "~2.0"
16 | },
17 | "dependencies": {},
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/MrMufflon/Leaflet.Coordinates.git"
21 | },
22 | "main": "dist/Leaflet.Coordinates-0.1.5.src.js",
23 | "keywords": [
24 | "gis",
25 | "coordinates",
26 | "leaflet",
27 | "map",
28 | "sdi"
29 | ],
30 | "author": "Felix Bache",
31 | "licenses": [{
32 | "type": "CC BY 3",
33 | "url": "http://creativecommons.org/licenses/by/3.0/"
34 | }],
35 | "readmeFilename": "README.md",
36 | "gitHead": "3b5c7d7af4f735c9bb2a925aa0c4a839f61bb470",
37 | "bugs": {
38 | "url": "https://github.com/MrMufflon/Leaflet.Coordinates/issues"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/spec/Grunt.Helper.js:
--------------------------------------------------------------------------------
1 | window.baseUrl = "http://localhost:9001";
--------------------------------------------------------------------------------
/spec/Number.Formatter.Spec.js:
--------------------------------------------------------------------------------
1 | describe('Number.Formatter', function() {
2 | var nf = L.NumberFormatter;
3 | it("formatts 9.27 correctly to DMS 9° 16' 12''", function() {
4 | expect(nf.toDMS(9.27)).toEqual("9° 16' 12''");
5 | });
6 | it("formatts -9.27 correctly to DMS -9° 16' 12''", function() {
7 | expect(nf.toDMS(-9.27)).toEqual("-9° 16' 12''");
8 | });
9 | it("formatts -9.1461 correctly to DMS -9° 08' 46''", function() {
10 | expect(nf.toDMS(-9.1461)).toEqual("-9° 08' 46''");
11 | });
12 | it("rounds -9.27334 correctly on 2 decimals with , seperator to -9,27", function() {
13 | expect(nf.round(-9.27334, 2, ",")).toEqual("-9,27");
14 | });
15 | it("rounds 9.27334 correctly on 4 decimals with , seperator to 9,2733", function() {
16 | expect(nf.round(9.27334, 4, ",")).toEqual("9,2733");
17 | });
18 | it("rounds 9.27394 correctly on 3 decimals with . seperator to 9.274", function() {
19 | expect(nf.round(9.27394, 3, ".")).toEqual("9.274");
20 | });
21 | it("rounds -9.27394 correctly on 3 decimals with . seperator to -9.274", function() {
22 | expect(nf.round(-9.27394, 3, ".")).toEqual("-9.274");
23 | });
24 | });
--------------------------------------------------------------------------------
/spec/SpecRunner.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 | Jasmine Spec Runner v2.0.0
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Control.Coordinates.css:
--------------------------------------------------------------------------------
1 |
2 | .leaflet-control-coordinates {
3 | background-color:#D8D8D8;
4 | background-color:rgba(255, 255, 255, 0.8);
5 | cursor:pointer;
6 | }
7 | .leaflet-control-coordinates,
8 | .leaflet-control-coordinates .uiElement input {
9 | -webkit-border-radius:5px;
10 | -moz-border-radius:5px;
11 | border-radius:5px;
12 | }
13 |
14 | .leaflet-control-coordinates .uiElement {
15 | margin:4px;
16 | }
17 |
18 | .leaflet-control-coordinates .uiElement .labelFirst {
19 | margin-right:4px;
20 | }
21 |
22 | .leaflet-control-coordinates .uiHidden{
23 | display:none;
24 | }
25 |
26 | .leaflet-control-coordinates .uiElement.label {
27 | color:inherit;
28 | font-weight: inherit;
29 | font-size: inherit;
30 | padding: 0;
31 | display: inherit;
32 | }
33 |
--------------------------------------------------------------------------------
/src/Control.Coordinates.ie.css:
--------------------------------------------------------------------------------
1 |
2 | .leaflet-control-coordinates {
3 | background-color:#D8D8D8;
4 | }
--------------------------------------------------------------------------------
/src/Control.Coordinates.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.Control.Coordinates is used for displaying current mouse coordinates on the map.
3 | */
4 |
5 | L.Control.Coordinates = L.Control.extend({
6 | options: {
7 | position: 'bottomright',
8 | //decimals used if not using DMS or labelFormatter functions
9 | decimals: 4,
10 | //decimalseperator used if not using DMS or labelFormatter functions
11 | decimalSeperator: ".",
12 | //label templates for usage if no labelFormatter function is defined
13 | labelTemplateLat: "Lat: {y}",
14 | labelTemplateLng: "Lng: {x}",
15 | //label formatter functions
16 | labelFormatterLat: undefined,
17 | labelFormatterLng: undefined,
18 | //switch on/off input fields on click
19 | enableUserInput: true,
20 | //use Degree-Minute-Second
21 | useDMS: false,
22 | //if true lat-lng instead of lng-lat label ordering is used
23 | useLatLngOrder: false,
24 | //if true user given coordinates are centered directly
25 | centerUserCoordinates: false,
26 | //leaflet marker type
27 | markerType: L.marker,
28 | //leaflet marker properties
29 | markerProps: {}
30 | },
31 |
32 | onAdd: function(map) {
33 | this._map = map;
34 |
35 | var className = 'leaflet-control-coordinates',
36 | container = this._container = L.DomUtil.create('div', className),
37 | options = this.options;
38 |
39 | //label containers
40 | this._labelcontainer = L.DomUtil.create("div", "uiElement label", container);
41 | this._label = L.DomUtil.create("span", "labelFirst", this._labelcontainer);
42 |
43 |
44 | //input containers
45 | this._inputcontainer = L.DomUtil.create("div", "uiElement input uiHidden", container);
46 | var xSpan, ySpan;
47 | if (options.useLatLngOrder) {
48 | ySpan = L.DomUtil.create("span", "", this._inputcontainer);
49 | this._inputY = this._createInput("inputY", this._inputcontainer);
50 | xSpan = L.DomUtil.create("span", "", this._inputcontainer);
51 | this._inputX = this._createInput("inputX", this._inputcontainer);
52 | } else {
53 | xSpan = L.DomUtil.create("span", "", this._inputcontainer);
54 | this._inputX = this._createInput("inputX", this._inputcontainer);
55 | ySpan = L.DomUtil.create("span", "", this._inputcontainer);
56 | this._inputY = this._createInput("inputY", this._inputcontainer);
57 | }
58 | xSpan.innerHTML = options.labelTemplateLng.replace("{x}", "");
59 | ySpan.innerHTML = options.labelTemplateLat.replace("{y}", "");
60 |
61 | L.DomEvent.on(this._inputX, 'keyup', this._handleKeypress, this);
62 | L.DomEvent.on(this._inputY, 'keyup', this._handleKeypress, this);
63 |
64 | //connect to mouseevents
65 | map.on("mousemove", this._update, this);
66 | map.on('dragstart', this.collapse, this);
67 |
68 | map.whenReady(this._update, this);
69 |
70 | this._showsCoordinates = true;
71 | //wether or not to show inputs on click
72 | if (options.enableUserInput) {
73 | L.DomEvent.addListener(this._container, "click", this._switchUI, this);
74 | }
75 |
76 | return container;
77 | },
78 |
79 | /**
80 | * Creates an input HTML element in given container with given classname
81 | */
82 | _createInput: function(classname, container) {
83 | var input = L.DomUtil.create("input", classname, container);
84 | input.type = "text";
85 | L.DomEvent.disableClickPropagation(input);
86 | return input;
87 | },
88 |
89 | _clearMarker: function() {
90 | this._map.removeLayer(this._marker);
91 | },
92 |
93 | /**
94 | * Called onkeyup of input fields
95 | */
96 | _handleKeypress: function(e) {
97 | switch (e.keyCode) {
98 | case 27: //Esc
99 | this.collapse();
100 | break;
101 | case 13: //Enter
102 | this._handleSubmit();
103 | this.collapse();
104 | break;
105 | default: //All keys
106 | this._handleSubmit();
107 | break;
108 | }
109 | },
110 |
111 | /**
112 | * Called on each keyup except ESC
113 | */
114 | _handleSubmit: function() {
115 | var x = L.NumberFormatter.createValidNumber(this._inputX.value, this.options.decimalSeperator);
116 | var y = L.NumberFormatter.createValidNumber(this._inputY.value, this.options.decimalSeperator);
117 | if (x !== undefined && y !== undefined) {
118 | var marker = this._marker;
119 | if (!marker) {
120 | marker = this._marker = this._createNewMarker();
121 | marker.on("click", this._clearMarker, this);
122 | }
123 | var ll = new L.LatLng(y, x);
124 | marker.setLatLng(ll);
125 | marker.addTo(this._map);
126 | if (this.options.centerUserCoordinates) {
127 | this._map.setView(ll, this._map.getZoom());
128 | }
129 | }
130 | },
131 |
132 | /**
133 | * Shows inputs fields
134 | */
135 | expand: function() {
136 | this._showsCoordinates = false;
137 |
138 | this._map.off("mousemove", this._update, this);
139 |
140 | L.DomEvent.addListener(this._container, "mousemove", L.DomEvent.stop);
141 | L.DomEvent.removeListener(this._container, "click", this._switchUI, this);
142 |
143 | L.DomUtil.addClass(this._labelcontainer, "uiHidden");
144 | L.DomUtil.removeClass(this._inputcontainer, "uiHidden");
145 | },
146 |
147 | /**
148 | * Creates the label according to given options and formatters
149 | */
150 | _createCoordinateLabel: function(ll) {
151 | var opts = this.options,
152 | x, y;
153 | if (opts.customLabelFcn) {
154 | return opts.customLabelFcn(ll, opts);
155 | }
156 | if (opts.labelFormatterLng) {
157 | x = opts.labelFormatterLng(ll.lng);
158 | } else {
159 | x = L.Util.template(opts.labelTemplateLng, {
160 | x: this._getNumber(ll.lng, opts)
161 | });
162 | }
163 | if (opts.labelFormatterLat) {
164 | y = opts.labelFormatterLat(ll.lat);
165 | } else {
166 | y = L.Util.template(opts.labelTemplateLat, {
167 | y: this._getNumber(ll.lat, opts)
168 | });
169 | }
170 | if (opts.useLatLngOrder) {
171 | return y + " " + x;
172 | }
173 | return x + " " + y;
174 | },
175 |
176 | /**
177 | * Returns a Number according to options (DMS or decimal)
178 | */
179 | _getNumber: function(n, opts) {
180 | var res;
181 | if (opts.useDMS) {
182 | res = L.NumberFormatter.toDMS(n);
183 | } else {
184 | res = L.NumberFormatter.round(n, opts.decimals, opts.decimalSeperator);
185 | }
186 | return res;
187 | },
188 |
189 | /**
190 | * Shows coordinate labels after user input has ended. Also
191 | * displays a marker with popup at the last input position.
192 | */
193 | collapse: function() {
194 | if (!this._showsCoordinates) {
195 | this._map.on("mousemove", this._update, this);
196 | this._showsCoordinates = true;
197 | var opts = this.options;
198 | L.DomEvent.addListener(this._container, "click", this._switchUI, this);
199 | L.DomEvent.removeListener(this._container, "mousemove", L.DomEvent.stop);
200 |
201 | L.DomUtil.addClass(this._inputcontainer, "uiHidden");
202 | L.DomUtil.removeClass(this._labelcontainer, "uiHidden");
203 |
204 | if (this._marker) {
205 | var m = this._createNewMarker(),
206 | ll = this._marker.getLatLng();
207 | m.setLatLng(ll);
208 |
209 | var container = L.DomUtil.create("div", "");
210 | var label = L.DomUtil.create("div", "", container);
211 | label.innerHTML = this._ordinateLabel(ll);
212 |
213 | var close = L.DomUtil.create("a", "", container);
214 | close.innerHTML = "Remove";
215 | close.href = "#";
216 | var stop = L.DomEvent.stopPropagation;
217 |
218 | L.DomEvent
219 | .on(close, 'click', stop)
220 | .on(close, 'mousedown', stop)
221 | .on(close, 'dblclick', stop)
222 | .on(close, 'click', L.DomEvent.preventDefault)
223 | .on(close, 'click', function() {
224 | this._map.removeLayer(m);
225 | }, this);
226 |
227 | m.bindPopup(container);
228 | m.addTo(this._map);
229 | this._map.removeLayer(this._marker);
230 | this._marker = null;
231 | }
232 | }
233 | },
234 |
235 | /**
236 | * Click callback for UI
237 | */
238 | _switchUI: function(evt) {
239 | L.DomEvent.stop(evt);
240 | L.DomEvent.stopPropagation(evt);
241 | L.DomEvent.preventDefault(evt);
242 | if (this._showsCoordinates) {
243 | //show textfields
244 | this.expand();
245 | } else {
246 | //show coordinates
247 | this.collapse();
248 | }
249 | },
250 |
251 | onRemove: function(map) {
252 | map.off("mousemove", this._update, this);
253 | },
254 |
255 | /**
256 | * Mousemove callback function updating labels and input elements
257 | */
258 | _update: function(evt) {
259 | var pos = evt.latlng,
260 | opts = this.options;
261 | if (pos) {
262 | pos = pos.wrap();
263 | this._currentPos = pos;
264 | this._inputY.value = L.NumberFormatter.round(pos.lat, opts.decimals, opts.decimalSeperator);
265 | this._inputX.value = L.NumberFormatter.round(pos.lng, opts.decimals, opts.decimalSeperator);
266 | this._label.innerHTML = this._createCoordinateLabel(pos);
267 | }
268 | },
269 |
270 | _createNewMarker: function() {
271 | return this.options.markerType(null, this.options.markerProps);
272 | }
273 |
274 | });
275 |
276 | //constructor registration
277 | L.control.coordinates = function(options) {
278 | return new L.Control.Coordinates(options);
279 | };
280 |
281 | //map init hook
282 | L.Map.mergeOptions({
283 | coordinateControl: false
284 | });
285 |
286 | L.Map.addInitHook(function() {
287 | if (this.options.coordinateControl) {
288 | this.coordinateControl = new L.Control.Coordinates();
289 | this.addControl(this.coordinateControl);
290 | }
291 | });
292 |
--------------------------------------------------------------------------------
/src/util/NumberFormatter.js:
--------------------------------------------------------------------------------
1 | L.NumberFormatter = {
2 | round: function(num, dec, sep) {
3 | var res = L.Util.formatNum(num, dec) + "",
4 | numbers = res.split(".");
5 | if (numbers[1]) {
6 | var d = dec - numbers[1].length;
7 | for (; d > 0; d--) {
8 | numbers[1] += "0";
9 | }
10 | res = numbers.join(sep || ".");
11 | }
12 | return res;
13 | },
14 |
15 | toDMS: function(deg) {
16 | var d = Math.floor(Math.abs(deg));
17 | var minfloat = (Math.abs(deg) - d) * 60;
18 | var m = Math.floor(minfloat);
19 | var secfloat = (minfloat - m) * 60;
20 | var s = Math.round(secfloat);
21 | if (s == 60) {
22 | m++;
23 | s = "00";
24 | }
25 | if (m == 60) {
26 | d++;
27 | m = "00";
28 | }
29 | if (s < 10) {
30 | s = "0" + s;
31 | }
32 | if (m < 10) {
33 | m = "0" + m;
34 | }
35 | var dir = "";
36 | if (deg < 0) {
37 | dir = "-";
38 | }
39 | return ("" + dir + d + "° " + m + "' " + s + "''");
40 | },
41 |
42 | createValidNumber: function(num, sep) {
43 | if (num && num.length > 0) {
44 | var numbers = num.split(sep || ".");
45 | try {
46 | var numRes = Number(numbers.join("."));
47 | if (isNaN(numRes)) {
48 | return undefined;
49 | }
50 | return numRes;
51 | } catch (e) {
52 | return undefined;
53 | }
54 | }
55 | return undefined;
56 | }
57 | };
--------------------------------------------------------------------------------