mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 01:53:33 -06:00
removed map2panel
This commit is contained in:
parent
569df6c88f
commit
9cf6a524df
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* Hexagonal binning
|
||||
* Rendered as normally projected svg paths, which mean they *do not*
|
||||
* clip on spheres appropriately. To fix this, we would need to translate
|
||||
* the svg path into a geo-path
|
||||
*/
|
||||
function displayBinning(scope, dr, dimensions) {
|
||||
|
||||
var hexbin = d3.hexbin()
|
||||
.size(dimensions)
|
||||
.radius(scope.panel.display.binning.hexagonSize);
|
||||
|
||||
|
||||
var binPoints = [],
|
||||
binnedPoints = [],
|
||||
binRange = 0;
|
||||
|
||||
|
||||
if (scope.panel.display.binning.enabled) {
|
||||
/**
|
||||
* primary field is just binning raw counts
|
||||
*
|
||||
* Secondary field is binning some metric like mean/median/total. Hexbins doesn't support that,
|
||||
* so we cheat a little and just add more points to compensate.
|
||||
* However, we don't want to add a million points, so normalize against the largest value
|
||||
*/
|
||||
if (scope.panel.display.binning.areaEncodingField === 'secondary') {
|
||||
var max = Math.max.apply(Math, _.map(scope.data, function(k,v){return k;})),
|
||||
scale = 50/max;
|
||||
|
||||
_.map(scope.data, function (k, v) {
|
||||
var decoded = geohash.decode(v);
|
||||
return _.map(_.range(0, k*scale), function(a,b) {
|
||||
binPoints.push(dr.projection([decoded.longitude, decoded.latitude]));
|
||||
})
|
||||
});
|
||||
|
||||
} else {
|
||||
binPoints = dr.projectedPoints;
|
||||
}
|
||||
|
||||
//bin and sort the points, so we can set the various ranges appropriately
|
||||
binnedPoints = hexbin(binPoints).sort(function(a, b) { return b.length - a.length; });
|
||||
binRange = binnedPoints[0].length;
|
||||
|
||||
//clean up some memory
|
||||
binPoints = [];
|
||||
} else {
|
||||
|
||||
//not enabled, so just set an empty array. D3.exit will take care of the rest
|
||||
binnedPoints = [];
|
||||
binRange = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var radius = d3.scale.sqrt()
|
||||
.domain([0, binRange])
|
||||
.range([0, scope.panel.display.binning.hexagonSize]);
|
||||
|
||||
var color = d3.scale.linear()
|
||||
.domain([0,binRange])
|
||||
.range(["white", "steelblue"])
|
||||
.interpolate(d3.interpolateLab);
|
||||
|
||||
|
||||
var hex = dr.g.selectAll(".hexagon")
|
||||
.data(binnedPoints);
|
||||
|
||||
hex.enter().append("path")
|
||||
.attr("d", function (d) {
|
||||
if (scope.panel.display.binning.areaEncoding === false) {
|
||||
return hexbin.hexagon();
|
||||
} else {
|
||||
return hexbin.hexagon(radius(d.length));
|
||||
}
|
||||
})
|
||||
.attr("class", "hexagon")
|
||||
.attr("transform", function (d) {
|
||||
return "translate(" + d.x + "," + d.y + ")";
|
||||
})
|
||||
.style("fill", function (d) {
|
||||
if (scope.panel.display.binning.colorEncoding === false) {
|
||||
return color(binnedPoints[0].length / 2);
|
||||
} else {
|
||||
return color(d.length);
|
||||
}
|
||||
})
|
||||
.attr("opacity", scope.panel.display.binning.hexagonAlpha);
|
||||
|
||||
hex.exit().remove();
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Renders bullseyes as geo-json poly gon entities
|
||||
* Allows for them to clip on spheres correctly
|
||||
*/
|
||||
function displayBullseye(scope, dr) {
|
||||
|
||||
var degrees = 180 / Math.PI
|
||||
var circle = d3.geo.circle();
|
||||
var data = [];
|
||||
|
||||
if (scope.panel.display.bullseye.enabled) {
|
||||
data = [
|
||||
circle.origin(parseFloat(scope.panel.display.bullseye.coord.lat), parseFloat(scope.panel.display.bullseye.coord.lon)).angle(1000 / 6371 * degrees)()
|
||||
];
|
||||
}
|
||||
|
||||
var arcs = dr.g.selectAll(".arc")
|
||||
.data(data);
|
||||
|
||||
arcs.enter().append("path")
|
||||
|
||||
.attr("d", dr.path)
|
||||
.attr("class", "arc");
|
||||
|
||||
arcs.exit().remove();
|
||||
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Renders geopoints as geo-json poly gon entities
|
||||
* Allows for them to clip on spheres correctly
|
||||
*/
|
||||
function displayGeopoints(scope, dr) {
|
||||
|
||||
var points = [];
|
||||
var circle = d3.geo.circle();
|
||||
var degrees = 180 / Math.PI
|
||||
|
||||
if (scope.panel.display.geopoints.enabled) {
|
||||
//points = dr.points;
|
||||
|
||||
points = _.map(dr.points, function(v) {
|
||||
return {
|
||||
type: "Point",
|
||||
coordinates: [v[0], v[1]]
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
dr.geopoints = dr.g.selectAll("path.geopoint")
|
||||
.data(points);
|
||||
|
||||
|
||||
|
||||
dr.geopoints.enter().append("path")
|
||||
/*
|
||||
.datum(function(d) {
|
||||
return circle.origin([d[0], d[1]]).angle(scope.panel.display.geopoints.pointSize / 6371 * degrees)();
|
||||
})
|
||||
*/
|
||||
.attr("class", "geopoint")
|
||||
.attr("d", dr.path);
|
||||
|
||||
dr.geopoints.exit().remove();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
<style>
|
||||
.tabDetails {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom:20px;
|
||||
}
|
||||
.tabDetails td {
|
||||
padding-right: 10px;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
</style>
|
||||
<div ng-controller="map2">
|
||||
<div class="row-fluid" style="margin-bottom:20px">
|
||||
<div class="span11">
|
||||
The map panel is compatible with either Geopoints or two-letter country codes, depending on the graphing options. Left click to drag/pan map, scroll wheel (or double click) to zoom. Globes can be spun using ctrl-key + drag.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span10">
|
||||
<form class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="panelfield">Primary Field</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="panelfield" class="input"
|
||||
ng-model="panel.field"
|
||||
ng-change="get_data()" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="panelsecondaryfield">Secondary Field</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="panelsecondaryfield" class="input"
|
||||
ng-model="panel.secondaryfield"
|
||||
ng-change="get_data()"
|
||||
data-placement="right"
|
||||
placeholder="Optional"
|
||||
bs-tooltip="'Allows aggregating on Primary field, while counting stats on a secondary (e.g. Group By user_id, Sum(purchase_price)).'" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="panelquery">Query</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="panelquery" class="input" ng-model="panel.query">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span11">
|
||||
<h4>Display Options</h4>
|
||||
</div>
|
||||
<!--
|
||||
Rolling our own tab control here because the Angular-Strap Tab directive doesn't allow
|
||||
updates to components inside, which is quite bizarre. Or I just can't figure it out...
|
||||
-->
|
||||
|
||||
<div class="span11">
|
||||
<ul class="nav nav-tabs" ng-cloak="">
|
||||
<li ng-repeat="tab in ['Geopoints', 'Binning', 'Choropleth', 'Bullseye', 'Data']" ng-class="{active:isActive(tab)}">
|
||||
<a ng-click="tabClick(tab)">{{tab}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid tabDetails" ng-show="isActive('geopoints')">
|
||||
<div class="span8 offset1">
|
||||
<table>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>Geopoints</td>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
data-placement="right"
|
||||
bs-tooltip="'Compatible with Geopoint Type'"
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.geopoints.enabled}"
|
||||
ng-model="panel.display.geopoints.enabled">{{panel.display.geopoints.enabled|enabledText}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Point size</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Controls the size of the geopoints on the map.'"
|
||||
ng-model="panel.display.geopoints.pointSize"
|
||||
value="{{panel.display.geopoints.pointSize}}" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Point Transparency</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Controls the transparency of geopoints. Valid numbers are between 0.0 and 1.0'"
|
||||
ng-model="panel.display.geopoints.pointAlpha"
|
||||
value="{{panel.display.geopoints.pointAlpha}}" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Autosizing</td>
|
||||
<td>
|
||||
<input type="checkbox"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
ng-model="panel.display.geopoints.autosize"
|
||||
bs-tooltip="'Allows point sizes to scale as you zoom in and out of the map.'" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid tabDetails" ng-show="isActive('binning')">
|
||||
<div class="span8 offset1">
|
||||
<table>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>Binning</td>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
data-placement="right"
|
||||
bs-tooltip="'Compatible with Geopoint Type'"
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.binning.enabled}"
|
||||
ng-model="panel.display.binning.enabled">{{panel.display.binning.enabled|enabledText}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hexagon size</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Controls the size of the hexagonal binning'"
|
||||
ng-model="panel.display.binning.hexagonSize"
|
||||
value="{{panel.display.binning.hexagonSize}}" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hexagon Transparency</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Controls the transparency of hexagonal bins. Valid numbers are between 0.0 and 1.0'"
|
||||
ng-model="panel.display.binning.hexagonAlpha"
|
||||
value="{{panel.display.binning.hexagonAlpha}}" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.binning.areaEncoding}"
|
||||
ng-model="panel.display.binning.areaEncoding">Area</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" ng-model="panel.display.binning.areaEncodingField" bs-buttons-radio ng-change="$emit('render')">
|
||||
<button type="button" class="btn" value="primary">Primary Field</button>
|
||||
<button type="button" class="btn" value="secondary">Secondary Field</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.binning.colorEncoding}"
|
||||
ng-model="panel.display.binning.colorEncoding">Color</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" ng-model="panel.display.binning.colorEncodingField" bs-buttons-radio ng-change="$emit('render')">
|
||||
<button type="button" class="btn" value="primary">Primary Field</button>
|
||||
<button type="button" class="btn" value="secondary">Secondary Field</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid tabDetails" ng-show="isActive('choropleth')">
|
||||
<div class="span8 offset1">
|
||||
<table>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>Choropleth</td>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
data-placement="right"
|
||||
bs-tooltip="'Choropleths color country regions according to your selected field. Compatible with Country-Coded fields'"
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.choropleth.enabled}"
|
||||
ng-model="panel.display.choropleth.enabled">{{panel.display.choropleth.enabled|enabledText}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid tabDetails" ng-show="isActive('bullseye')">
|
||||
<div class="span8 offset1">
|
||||
<table>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>Bullseye</td>
|
||||
<td>
|
||||
<button type="button" class="btn" bs-button
|
||||
ng-change="$emit('render')"
|
||||
ng-class="{'btn-success': panel.display.bullseye.enabled}"
|
||||
ng-model="panel.display.bullseye.enabled">{{panel.display.bullseye.enabled|enabledText}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bullseye Coordinates</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="$emit('render')"
|
||||
placeholder="Latitude"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Latitude of Bullseye'"
|
||||
ng-model="panel.display.bullseye.coord.lat"
|
||||
value="{{panel.display.bullseye.coord.lat}}" />
|
||||
|
||||
<input type="text" style="width:100px"
|
||||
placeholder="Longitude"
|
||||
ng-change="$emit('render')"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Longitude of Bullseye'"
|
||||
ng-model="panel.display.bullseye.coord.lon"
|
||||
value="{{panel.display.bullseye.coord.lon}}" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid tabDetails" ng-show="isActive('data')">
|
||||
<div class="span8 offset1">
|
||||
<table>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>Data Points</td>
|
||||
<td>
|
||||
<input type="text" style="width:100px"
|
||||
ng-change="get_data()"
|
||||
data-placement="right"
|
||||
bs-tooltip="'Controls the number of samples used in the map. Be careful with this value!'"
|
||||
ng-model="panel.display.data.samples"
|
||||
value="{{panel.display.data.samples}}" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Map Projection</td>
|
||||
<td>
|
||||
<select ng-model="panel.display.data.type" ng-options="option.id as option.text for option in panel.display.data.dropdown"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Panel Spy</h5>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<label class="small">Spyable</label> <input type="checkbox" ng-model=
|
||||
"panel.spyable" ng-checked="panel.spyable">
|
||||
</div>
|
||||
|
||||
<div class="span9 small">
|
||||
The panel spy shows 'behind the scenes' information about a panel. It can be
|
||||
accessed by clicking the in the top right of the panel.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
1
panels/map2/lib/d3.hexbin.v0.min.js
vendored
1
panels/map2/lib/d3.hexbin.v0.min.js
vendored
@ -1 +0,0 @@
|
||||
(function(){d3.hexbin=function(){function u(n){var r={};return n.forEach(function(n,t){var a=s.call(u,n,t)/o,e=Math.round(a),h=f.call(u,n,t)/i-(1&e?.5:0),c=Math.round(h),l=a-e;if(3*Math.abs(l)>1){var g=h-c,v=c+(c>h?-1:1)/2,M=e+(e>a?-1:1),m=h-v,d=a-M;g*g+l*l>m*m+d*d&&(c=v+(1&e?1:-1)/2,e=M)}var x=c+"-"+e,j=r[x];j?j.push(n):(j=r[x]=[n],j.x=(c+(1&e?.5:0))*i,j.y=e*o)}),d3.values(r)}function a(r){var t=0,u=0;return n.map(function(n){var a=Math.sin(n)*r,e=-Math.cos(n)*r,i=a-t,o=e-u;return t=a,u=e,[i,o]})}var e,i,o,h=1,c=1,f=r,s=t;return u.x=function(n){return arguments.length?(f=n,u):f},u.y=function(n){return arguments.length?(s=n,u):s},u.hexagon=function(n){return 1>arguments.length&&(n=e),"m"+a(n).join("l")+"z"},u.mesh=function(){for(var n=[],r=a(e).slice(0,4).join("l"),t=0,u=!1;c+e>t;t+=o,u=!u)for(var f=u?i/2:0;h>f;f+=i)n.push("M",f,",",t,"m",r);return n.join("")},u.size=function(n){return arguments.length?(h=+n[0],c=+n[1],u):[h,c]},u.radius=function(n){return arguments.length?(e=+n,i=2*e*Math.sin(Math.PI/3),o=1.5*e,u):e},u.radius(1)};var n=d3.range(0,2*Math.PI,Math.PI/3),r=function(n){return n[0]},t=function(n){return n[1]}})();
|
@ -1,137 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2011, Sun Ning.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
var BASE32_CODES = "0123456789bcdefghjkmnpqrstuvwxyz";
|
||||
var BASE32_CODES_DICT = {};
|
||||
for(var i=0; i<BASE32_CODES.length; i++) {
|
||||
BASE32_CODES_DICT[BASE32_CODES.charAt(i)]=i;
|
||||
}
|
||||
|
||||
var encode = function(latitude, longitude, numberOfChars){
|
||||
numberOfChars = numberOfChars || 9;
|
||||
var chars = [], bits = 0;
|
||||
var hash_value = 0;
|
||||
|
||||
var maxlat = 90, minlat = -90;
|
||||
var maxlon = 180, minlon = -180;
|
||||
|
||||
var mid;
|
||||
var islon = true;
|
||||
while(chars.length < numberOfChars) {
|
||||
if (islon){
|
||||
mid = (maxlon+minlon)/2;
|
||||
if(longitude > mid){
|
||||
hash_value = (hash_value << 1) + 1;
|
||||
minlon=mid;
|
||||
} else {
|
||||
hash_value = (hash_value << 1) + 0;
|
||||
maxlon=mid;
|
||||
}
|
||||
} else {
|
||||
mid = (maxlat+minlat)/2;
|
||||
if(latitude > mid ){
|
||||
hash_value = (hash_value << 1) + 1;
|
||||
minlat = mid;
|
||||
} else {
|
||||
hash_value = (hash_value << 1) + 0;
|
||||
maxlat = mid;
|
||||
}
|
||||
}
|
||||
islon = !islon;
|
||||
|
||||
bits++;
|
||||
if (bits == 5) {
|
||||
var code = BASE32_CODES[hash_value];
|
||||
chars.push(code);
|
||||
bits = 0;
|
||||
hash_value = 0;
|
||||
}
|
||||
}
|
||||
return chars.join('')
|
||||
};
|
||||
|
||||
var decode_bbox = function(hash_string){
|
||||
var islon = true;
|
||||
var maxlat = 90, minlat = -90;
|
||||
var maxlon = 180, minlon = -180;
|
||||
|
||||
var hash_value = 0;
|
||||
for(var i=0,l=hash_string.length; i<l; i++) {
|
||||
var code = hash_string[i].toLowerCase();
|
||||
hash_value = BASE32_CODES_DICT[code];
|
||||
|
||||
for (var bits=4; bits>=0; bits--) {
|
||||
var bit = (hash_value >> bits) & 1;
|
||||
if (islon){
|
||||
var mid = (maxlon+minlon)/2;
|
||||
if(bit == 1){
|
||||
minlon = mid;
|
||||
} else {
|
||||
maxlon = mid;
|
||||
}
|
||||
} else {
|
||||
var mid = (maxlat+minlat)/2;
|
||||
if(bit == 1){
|
||||
minlat = mid;
|
||||
} else {
|
||||
maxlat = mid;
|
||||
}
|
||||
}
|
||||
islon = !islon;
|
||||
}
|
||||
}
|
||||
return [minlat, minlon, maxlat, maxlon];
|
||||
}
|
||||
|
||||
var decode = function(hash_string){
|
||||
var bbox = decode_bbox(hash_string);
|
||||
var lat = (bbox[0]+bbox[2])/2;
|
||||
var lon = (bbox[1]+bbox[3])/2;
|
||||
var laterr = bbox[2]-lat;
|
||||
var lonerr = bbox[3]-lon;
|
||||
return {latitude:lat, longitude:lon,
|
||||
error:{latitude:laterr, longitude:lonerr}};
|
||||
};
|
||||
|
||||
/**
|
||||
* direction [lat, lon], i.e.
|
||||
* [1,0] - north
|
||||
* [1,1] - northeast
|
||||
* ...
|
||||
*/
|
||||
var neighbor = function(hashstring, direction) {
|
||||
var lonlat = decode(hashstring);
|
||||
var neighbor_lat = lonlat.latitude
|
||||
+ direction[0] * lonlat.error.latitude * 2;
|
||||
var neighbor_lon = lonlat.longitude
|
||||
+ direction[1] * lonlat.error.longitude * 2;
|
||||
return encode(neighbor_lat, neighbor_lon, hashstring.length);
|
||||
}
|
||||
|
||||
var geohash = {
|
||||
'encode': encode,
|
||||
'decode': decode,
|
||||
'decode_bbox': decode_bbox,
|
||||
'neighbor': neighbor,
|
||||
}
|
||||
module.exports = geohash;
|
1
panels/map2/lib/queue.v1.min.js
vendored
1
panels/map2/lib/queue.v1.min.js
vendored
@ -1 +0,0 @@
|
||||
(function(){function n(n){function t(){for(;f=a<c.length&&n>p;){var u=a++,t=c[u],r=l.call(t,1);r.push(e(u)),++p,t[0].apply(null,r)}}function e(n){return function(u,l){--p,null==d&&(null!=u?(d=u,a=s=0/0,r()):(c[n]=l,--s?f||t():r()))}}function r(){null!=d?v(d):i?v(d,c):v.apply(null,[d].concat(c))}var o,f,i,c=[],a=0,p=0,s=0,d=null,v=u;return n||(n=1/0),o={defer:function(){return d||(c.push(arguments),++s,t()),o},await:function(n){return v=n,i=!1,s||r(),o},awaitAll:function(n){return v=n,i=!0,s||r(),o}}}function u(){}"undefined"==typeof module?self.queue=n:module.exports=n,n.version="1.0.4";var l=[].slice})();
|
1
panels/map2/lib/topojson.v1.min.js
vendored
1
panels/map2/lib/topojson.v1.min.js
vendored
@ -1 +0,0 @@
|
||||
topojson=function(){function t(t,e){function n(e){var n=t.arcs[e],r=n[0],o=[0,0];return n.forEach(function(t){o[0]+=t[0],o[1]+=t[1]}),[r,o]}var r={},o={},a={};e.forEach(function(t){var e=n(t);(r[e[0]]||(r[e[0]]=[])).push(t),(r[e[1]]||(r[e[1]]=[])).push(~t)}),e.forEach(function(t){var e,r,i=n(t),u=i[0],c=i[1];if(e=a[u])if(delete a[e.end],e.push(t),e.end=c,r=o[c]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=a[c]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else if(e=o[c])if(delete o[e.start],e.unshift(t),e.start=u,r=a[u]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[u]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=o[u])if(delete o[e.start],e.unshift(~t),e.start=c,r=a[c]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[c]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=a[c])if(delete a[e.end],e.push(~t),e.end=u,r=a[u]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=o[u]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else e=[t],o[e.start=u]=a[e.end=c]=e});var i=[];for(var u in a)i.push(a[u]);return i}function e(e,n,r){function a(t){0>t&&(t=~t),(l[t]||(l[t]=[])).push(f)}function i(t){t.forEach(a)}function u(t){t.forEach(i)}function c(t){t.type==="GeometryCollection"?t.geometries.forEach(c):t.type in d&&(f=t,d[t.type](t.arcs))}var s=[];if(arguments.length>1){var f,l=[],d={LineString:i,MultiLineString:u,Polygon:u,MultiPolygon:function(t){t.forEach(u)}};c(n),l.forEach(arguments.length<3?function(t,e){s.push([e])}:function(t,e){r(t[0],t[t.length-1])&&s.push([e])})}else for(var p=0,h=e.arcs.length;h>p;++p)s.push([p]);return o(e,{type:"MultiLineString",arcs:t(e,s)})}function n(t,e){return e.type==="GeometryCollection"?{type:"FeatureCollection",features:e.geometries.map(function(e){return r(t,e)})}:r(t,e)}function r(t,e){var n={type:"Feature",id:e.id,properties:e.properties||{},geometry:o(t,e)};return e.id==null&&delete n.id,n}function o(t,e){function n(t,e){e.length&&e.pop();for(var n,r=h[0>t?~t:t],o=0,i=r.length,u=0,c=0;i>o;++o)e.push([(u+=(n=r[o])[0])*f+d,(c+=n[1])*l+p]);0>t&&a(e,i)}function r(t){return[t[0]*f+d,t[1]*l+p]}function o(t){for(var e=[],r=0,o=t.length;o>r;++r)n(t[r],e);return e.length<2&&e.push(e[0]),e}function i(t){for(var e=o(t);e.length<4;)e.push(e[0]);return e}function u(t){return t.map(i)}function c(t){var e=t.type;return"GeometryCollection"===e?{type:e,geometries:t.geometries.map(c)}:e in v?{type:e,coordinates:v[e](t)}:null}var s=t.transform,f=s.scale[0],l=s.scale[1],d=s.translate[0],p=s.translate[1],h=t.arcs,v={Point:function(t){return r(t.coordinates)},MultiPoint:function(t){return t.coordinates.map(r)},LineString:function(t){return o(t.arcs)},MultiLineString:function(t){return t.arcs.map(o)},Polygon:function(t){return u(t.arcs)},MultiPolygon:function(t){return t.arcs.map(u)}};return c(e)}function a(t,e){for(var n,r=t.length,o=r-e;o<--r;)n=t[o],t[o++]=t[r],t[r]=n}function i(t,e){for(var n=0,r=t.length;r>n;){var o=n+r>>>1;t[o]<e?n=o+1:r=o}return n}function u(t){function e(t,e){t.forEach(function(t){0>t&&(t=~t);var n=o[t]||(o[t]=[]);n[e]||(n.forEach(function(t){var n,r;r=i(n=a[e],t),n[r]!==t&&n.splice(r,0,t),r=i(n=a[t],e),n[r]!==e&&n.splice(r,0,e)}),n[e]=e)})}function n(t,n){t.forEach(function(t){e(t,n)})}function r(t,e){t.type==="GeometryCollection"?t.geometries.forEach(function(t){r(t,e)}):t.type in u&&u[t.type](t.arcs,e)}var o=[],a=t.map(function(){return[]}),u={LineString:e,MultiLineString:n,Polygon:n,MultiPolygon:function(t,e){t.forEach(function(t){n(t,e)})}};return t.forEach(r),a}return{version:"1.0.0pre",mesh:e,feature:n,neighbors:u}}();
|
File diff suppressed because one or more lines are too long
@ -1,251 +0,0 @@
|
||||
id short name
|
||||
4 AF Afghanistan
|
||||
8 AL Albania
|
||||
10 AQ Antarctica
|
||||
12 DZ Algeria
|
||||
16 AS American Samoa
|
||||
20 AD Andorra
|
||||
24 AO Angola
|
||||
28 AG Antigua and Barbuda
|
||||
31 AZ Azerbaijan
|
||||
32 AR Argentina
|
||||
36 AU Australia
|
||||
40 AT Austria
|
||||
44 BS Bahamas
|
||||
48 BH Bahrain
|
||||
50 BD Bangladesh
|
||||
51 AM Armenia
|
||||
52 BB Barbados
|
||||
56 BE Belgium
|
||||
60 BM Bermuda
|
||||
64 BT Bhutan
|
||||
68 BO Bolivia, Plurinational State of
|
||||
70 BA Bosnia and Herzegovina
|
||||
72 BW Botswana
|
||||
74 BV Bouvet Island
|
||||
76 BR Brazil
|
||||
84 BZ Belize
|
||||
86 IO British Indian Ocean Territory
|
||||
90 SB Solomon Islands
|
||||
92 VG Virgin Islands, British
|
||||
96 BN Brunei Darussalam
|
||||
100 BG Bulgaria
|
||||
104 MM Myanmar
|
||||
108 BI Burundi
|
||||
112 BY Belarus
|
||||
116 KH Cambodia
|
||||
120 CM Cameroon
|
||||
124 CA Canada
|
||||
132 CV Cape Verde
|
||||
136 KY Cayman Islands
|
||||
140 CF Central African Republic
|
||||
144 LK Sri Lanka
|
||||
148 TD Chad
|
||||
152 CL Chile
|
||||
156 CN China
|
||||
158 TW Taiwan, Province of China
|
||||
162 CX Christmas Island
|
||||
166 CC Cocos (Keeling) Islands
|
||||
170 CO Colombia
|
||||
174 KM Comoros
|
||||
175 YT Mayotte
|
||||
178 CG Congo
|
||||
180 CD Congo, the Democratic Republic of the
|
||||
184 CK Cook Islands
|
||||
188 CR Costa Rica
|
||||
191 HR Croatia
|
||||
192 CU Cuba
|
||||
196 CY Cyprus
|
||||
203 CZ Czech Republic
|
||||
204 BJ Benin
|
||||
208 DK Denmark
|
||||
212 DM Dominica
|
||||
214 DO Dominican Republic
|
||||
218 EC Ecuador
|
||||
222 SV El Salvador
|
||||
226 GQ Equatorial Guinea
|
||||
231 ET Ethiopia
|
||||
232 ER Eritrea
|
||||
233 EE Estonia
|
||||
234 FO Faroe Islands
|
||||
238 FK Falkland Islands (Malvinas)
|
||||
239 GS South Georgia and the South Sandwich Islands
|
||||
242 FJ Fiji
|
||||
246 FI Finland
|
||||
248 AX Åland Islands
|
||||
250 FR France
|
||||
254 GF French Guiana
|
||||
258 PF French Polynesia
|
||||
260 TF French Southern Territories
|
||||
262 DJ Djibouti
|
||||
266 GA Gabon
|
||||
268 GE Georgia
|
||||
270 GM Gambia
|
||||
275 Palestinian Territory, Occupied
|
||||
276 DE Germany
|
||||
288 GH Ghana
|
||||
292 GI Gibraltar
|
||||
296 KI Kiribati
|
||||
300 GR Greece
|
||||
304 GL Greenland
|
||||
308 GD Grenada
|
||||
312 GP Guadeloupe
|
||||
316 GU Guam
|
||||
320 GT Guatemala
|
||||
324 GN Guinea
|
||||
328 GY Guyana
|
||||
332 HT Haiti
|
||||
334 HM Heard Island and McDonald Islands
|
||||
336 VA Holy See (Vatican City State)
|
||||
340 HN Honduras
|
||||
344 HK Hong Kong
|
||||
348 HU Hungary
|
||||
352 IS Iceland
|
||||
356 IN India
|
||||
360 ID Indonesia
|
||||
364 IR Iran, Islamic Republic of
|
||||
368 IQ Iraq
|
||||
372 IE Ireland
|
||||
376 IL Israel
|
||||
380 IT Italy
|
||||
384 Côte d'Ivoire
|
||||
388 JM Jamaica
|
||||
392 JP Japan
|
||||
398 KZ Kazakhstan
|
||||
400 JO Jordan
|
||||
404 KE Kenya
|
||||
408 KP Korea, Democratic People's Republic of
|
||||
410 KR Korea, Republic of
|
||||
414 KW Kuwait
|
||||
417 KG Kyrgyzstan
|
||||
418 LA Lao People's Democratic Republic
|
||||
422 LB Lebanon
|
||||
426 LS Lesotho
|
||||
428 LV Latvia
|
||||
430 LR Liberia
|
||||
434 LY Libya
|
||||
438 LI Liechtenstein
|
||||
440 LT Lithuania
|
||||
442 LU Luxembourg
|
||||
446 MO Macao
|
||||
450 MG Madagascar
|
||||
454 MW Malawi
|
||||
458 MY Malaysia
|
||||
462 MV Maldives
|
||||
466 ML Mali
|
||||
470 MT Malta
|
||||
474 MQ Martinique
|
||||
478 MR Mauritania
|
||||
480 MU Mauritius
|
||||
484 MX Mexico
|
||||
492 MC Monaco
|
||||
496 MN Mongolia
|
||||
498 MD Moldova, Republic of
|
||||
499 ME Montenegro
|
||||
500 MS Montserrat
|
||||
504 MA Morocco
|
||||
508 MZ Mozambique
|
||||
512 OM Oman
|
||||
516 NA Namibia
|
||||
520 NR Nauru
|
||||
524 NP Nepal
|
||||
528 NL Netherlands
|
||||
531 Curaçao
|
||||
533 AW Aruba
|
||||
534 SX Sint Maarten (Dutch part)
|
||||
535 BQ Bonaire, Sint Eustatius and Saba
|
||||
540 NC New Caledonia
|
||||
548 VU Vanuatu
|
||||
554 NZ New Zealand
|
||||
558 NI Nicaragua
|
||||
562 NE Niger
|
||||
566 NG Nigeria
|
||||
570 NU Niue
|
||||
574 NF Norfolk Island
|
||||
578 NO Norway
|
||||
580 MP Northern Mariana Islands
|
||||
581 UM United States Minor Outlying Islands
|
||||
583 FM Micronesia, Federated States of
|
||||
584 MH Marshall Islands
|
||||
585 PW Palau
|
||||
586 PK Pakistan
|
||||
591 PA Panama
|
||||
598 PG Papua New Guinea
|
||||
600 PY Paraguay
|
||||
604 PE Peru
|
||||
608 PH Philippines
|
||||
612 PN Pitcairn
|
||||
616 PL Poland
|
||||
620 PT Portugal
|
||||
624 GW Guinea-Bissau
|
||||
626 TL Timor-Leste
|
||||
630 PR Puerto Rico
|
||||
634 QA Qatar
|
||||
638 Réunion
|
||||
642 RO Romania
|
||||
643 RU Russian Federation
|
||||
646 RW Rwanda
|
||||
652 Saint Barthélemy
|
||||
654 SH Saint Helena, Ascension and Tristan da Cunha
|
||||
659 KN Saint Kitts and Nevis
|
||||
660 AI Anguilla
|
||||
662 LC Saint Lucia
|
||||
663 MF Saint Martin (French part)
|
||||
666 PM Saint Pierre and Miquelon
|
||||
670 VC Saint Vincent and the Grenadines
|
||||
674 SM San Marino
|
||||
678 ST Sao Tome and Principe
|
||||
682 SA Saudi Arabia
|
||||
686 SN Senegal
|
||||
688 RS Serbia
|
||||
690 SC Seychelles
|
||||
694 SL Sierra Leone
|
||||
702 SG Singapore
|
||||
703 SK Slovakia
|
||||
704 VN Viet Nam
|
||||
705 SI Slovenia
|
||||
706 SO Somalia
|
||||
710 ZA South Africa
|
||||
716 ZW Zimbabwe
|
||||
724 ES Spain
|
||||
728 SS South Sudan
|
||||
729 SD Sudan
|
||||
732 EH Western Sahara
|
||||
740 SR Suriname
|
||||
744 SJ Svalbard and Jan Mayen
|
||||
748 SZ Swaziland
|
||||
752 SE Sweden
|
||||
756 CH Switzerland
|
||||
760 SY Syrian Arab Republic
|
||||
762 TJ Tajikistan
|
||||
764 TH Thailand
|
||||
768 TG Togo
|
||||
772 TK Tokelau
|
||||
776 TO Tonga
|
||||
780 TT Trinidad and Tobago
|
||||
784 AE United Arab Emirates
|
||||
788 TN Tunisia
|
||||
792 TR Turkey
|
||||
795 TM Turkmenistan
|
||||
796 TC Turks and Caicos Islands
|
||||
798 TV Tuvalu
|
||||
800 UG Uganda
|
||||
804 UA Ukraine
|
||||
807 MK Macedonia, the former Yugoslav Republic of
|
||||
818 EG Egypt
|
||||
826 GB United Kingdom
|
||||
831 GG Guernsey
|
||||
832 JE Jersey
|
||||
833 IM Isle of Man
|
||||
834 TZ Tanzania, United Republic of
|
||||
840 US United States
|
||||
850 VI Virgin Islands, U.S.
|
||||
854 BF Burkina Faso
|
||||
858 UY Uruguay
|
||||
860 UZ Uzbekistan
|
||||
862 VE Venezuela, Bolivarian Republic of
|
||||
876 WF Wallis and Futuna
|
||||
882 WS Samoa
|
||||
887 YE Yemen
|
||||
894 ZM Zambia
|
||||
|
|
@ -1,58 +0,0 @@
|
||||
<kibana-panel ng-controller='map2' ng-init="init()">
|
||||
<style>
|
||||
.overlay {
|
||||
fill: none;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.land {
|
||||
fill: #D1D1D1;
|
||||
stroke: #595959;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
stroke-width: .1px;
|
||||
}
|
||||
|
||||
.boundary {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
.hexagon {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-width: .1px;
|
||||
}
|
||||
|
||||
.q1 { fill:rgb(247,251,255); }
|
||||
.q2 { fill:rgb(222,235,247); }
|
||||
.q3 { fill:rgb(198,219,239); }
|
||||
.q4 { fill:rgb(158,202,225); }
|
||||
.q5 { fill:rgb(107,174,214); }
|
||||
.q6 { fill:rgb(66,146,198); }
|
||||
.q7 { fill:rgb(33,113,181); }
|
||||
.q8 { fill:rgb(8,81,156); }
|
||||
.q9 { fill:rgb(8,48,107); }
|
||||
|
||||
.arc {
|
||||
stroke: #f00;
|
||||
stroke-width: .5px;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.geopoint {
|
||||
stroke: #000;
|
||||
stroke-width: .5px;
|
||||
fill: #000;
|
||||
}
|
||||
|
||||
.dropdown-menu{position:absolute;top:auto;left:auto;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#ffffff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;}
|
||||
</style>
|
||||
<span ng-show="panel.spyable" style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
|
||||
<i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
|
||||
</span>
|
||||
|
||||
<div map2 params="{{panel}}" style="height:{{panel.height || row.height}}"></div>
|
||||
</kibana-panel>
|
@ -1,452 +0,0 @@
|
||||
angular.module('kibana.map2', [])
|
||||
.controller('map2', function ($scope, eventBus, keylistener) {
|
||||
|
||||
// Set and populate defaults
|
||||
var _d = {
|
||||
status : "Broken",
|
||||
query: "*",
|
||||
map: "world",
|
||||
colors: ['#C8EEFF', '#0071A4'],
|
||||
size: 100,
|
||||
exclude: [],
|
||||
spyable: true,
|
||||
group: "default",
|
||||
index_limit: 0,
|
||||
display: {
|
||||
translate:[0, 0],
|
||||
scale:-1,
|
||||
data: {
|
||||
samples: 1000,
|
||||
type: "mercator",
|
||||
dropdown:[
|
||||
{
|
||||
"text": "Mercator (Flat)",
|
||||
id: "mercator"
|
||||
},
|
||||
{
|
||||
text: "Orthographic (Sphere)",
|
||||
id: "orthographic"
|
||||
}
|
||||
]
|
||||
},
|
||||
geopoints: {
|
||||
enabled: false,
|
||||
enabledText: "Enabled",
|
||||
pointSize: 0.3,
|
||||
pointAlpha: 0.6
|
||||
},
|
||||
binning: {
|
||||
enabled: false,
|
||||
hexagonSize: 2,
|
||||
hexagonAlpha: 1.0,
|
||||
areaEncoding: true,
|
||||
areaEncodingField: "primary",
|
||||
colorEncoding: true,
|
||||
colorEncodingField: "primary"
|
||||
},
|
||||
choropleth: {
|
||||
enabled: false
|
||||
},
|
||||
bullseye: {
|
||||
enabled: false,
|
||||
coord: {
|
||||
lat: 0,
|
||||
lon: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
activeDisplayTab:"Geopoints"
|
||||
};
|
||||
|
||||
_.defaults($scope.panel, _d)
|
||||
|
||||
$scope.init = function () {
|
||||
eventBus.register($scope, 'time', function (event, time) {
|
||||
set_time(time)
|
||||
});
|
||||
eventBus.register($scope, 'query', function (event, query) {
|
||||
$scope.panel.query = _.isArray(query) ? query[0] : query;
|
||||
$scope.get_data();
|
||||
});
|
||||
// Now that we're all setup, request the time from our group
|
||||
eventBus.broadcast($scope.$id, $scope.panel.group, 'get_time');
|
||||
|
||||
$scope.keylistener = keylistener;
|
||||
|
||||
};
|
||||
|
||||
$scope.get_data = function () {
|
||||
|
||||
// Make sure we have everything for the request to complete
|
||||
if (_.isUndefined($scope.index) || _.isUndefined($scope.time))
|
||||
return
|
||||
|
||||
$scope.panel.loading = true;
|
||||
var request = $scope.ejs.Request().indices($scope.index);
|
||||
|
||||
|
||||
var metric = 'count';
|
||||
|
||||
//Use a regular term facet if there is no secondary field
|
||||
if (typeof $scope.panel.secondaryfield === "undefined") {
|
||||
var facet = $scope.ejs.TermsFacet('map')
|
||||
.field($scope.panel.field)
|
||||
.size($scope.panel.display.data.samples)
|
||||
.exclude($scope.panel.exclude)
|
||||
.facetFilter(ejs.QueryFilter(
|
||||
ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery($scope.panel.query || '*'),
|
||||
ejs.RangeFilter($scope.time.field)
|
||||
.from($scope.time.from)
|
||||
.to($scope.time.to))));
|
||||
|
||||
metric = 'count';
|
||||
} else {
|
||||
//otherwise, use term stats
|
||||
//NOTE: this will break if valueField is a geo_point
|
||||
// need to put in checks for that
|
||||
var facet = $scope.ejs.TermStatsFacet('map')
|
||||
.keyField($scope.panel.field)
|
||||
.valueField($scope.panel.secondaryfield)
|
||||
.size($scope.panel.display.data.samples)
|
||||
.facetFilter(ejs.QueryFilter(
|
||||
ejs.FilteredQuery(
|
||||
ejs.QueryStringQuery($scope.panel.query || '*'),
|
||||
ejs.RangeFilter($scope.time.field)
|
||||
.from($scope.time.from)
|
||||
.to($scope.time.to))));
|
||||
|
||||
metric = 'total';
|
||||
}
|
||||
|
||||
|
||||
// Then the insert into facet and make the request
|
||||
var request = request.facet(facet).size(0);
|
||||
|
||||
$scope.populate_modal(request);
|
||||
|
||||
var results = request.doSearch();
|
||||
|
||||
// Populate scope when we have results
|
||||
results.then(function (results) {
|
||||
$scope.panel.loading = false;
|
||||
$scope.hits = results.hits.total;
|
||||
$scope.data = {};
|
||||
|
||||
_.each(results.facets.map.terms, function (v) {
|
||||
|
||||
if (!_.isNumber(v.term)) {
|
||||
$scope.data[v.term.toUpperCase()] = v[metric];
|
||||
} else {
|
||||
$scope.data[v.term] = v[metric];
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$emit('render')
|
||||
});
|
||||
};
|
||||
|
||||
// I really don't like this function, too much dom manip. Break out into directive?
|
||||
$scope.populate_modal = function (request) {
|
||||
$scope.modal = {
|
||||
title: "Inspector",
|
||||
body: "<h5>Last Elasticsearch Query</h5><pre>" + 'curl -XGET ' + config.elasticsearch + '/' + $scope.index + "/_search?pretty -d'\n" + angular.toJson(JSON.parse(request.toString()), true) + "'</pre>"
|
||||
}
|
||||
};
|
||||
|
||||
function set_time(time) {
|
||||
$scope.time = time;
|
||||
$scope.index = _.isUndefined(time.index) ? $scope.index : time.index
|
||||
$scope.get_data();
|
||||
}
|
||||
|
||||
$scope.build_search = function (field, value) {
|
||||
$scope.panel.query = add_to_query($scope.panel.query, field, value, false)
|
||||
$scope.get_data();
|
||||
eventBus.broadcast($scope.$id, $scope.panel.group, 'query', $scope.panel.query);
|
||||
};
|
||||
|
||||
$scope.isActive = function(tab) {
|
||||
return (tab.toLowerCase() === $scope.panel.activeDisplayTab.toLowerCase());
|
||||
}
|
||||
|
||||
$scope.tabClick = function(tab) {
|
||||
$scope.panel.activeDisplayTab = tab;
|
||||
}
|
||||
|
||||
})
|
||||
.filter('enabledText', function() {
|
||||
return function (value) {
|
||||
if (value === true) {
|
||||
return "Enabled";
|
||||
} else {
|
||||
return "Disabled";
|
||||
}
|
||||
}
|
||||
})
|
||||
.directive('map2', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, elem, attrs) {
|
||||
|
||||
//directive level variables related to d3
|
||||
var dr = {};
|
||||
|
||||
scope.initializing = false;
|
||||
|
||||
|
||||
dr.worldData = null;
|
||||
dr.worldNames = null;
|
||||
|
||||
/**
|
||||
* Initialize the panels if new, or render existing panels
|
||||
*/
|
||||
scope.init_or_render = function() {
|
||||
if (typeof dr.svg === 'undefined') {
|
||||
console.log("init");
|
||||
|
||||
//prevent duplicate initialization steps, if render is called again
|
||||
//before the svg is setup
|
||||
if (!scope.initializing) {
|
||||
init_panel();
|
||||
}
|
||||
} else {
|
||||
console.log("render");
|
||||
render_panel();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive render events
|
||||
*/
|
||||
scope.$on('render', function () {
|
||||
scope.init_or_render();
|
||||
});
|
||||
|
||||
/**
|
||||
* On window resize, re-render the panel
|
||||
*/
|
||||
angular.element(window).bind('resize', function () {
|
||||
scope.init_or_render();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Load the various panel-specific scripts, map data, then initialize
|
||||
* the svg and set appropriate D3 settings
|
||||
*/
|
||||
function init_panel() {
|
||||
|
||||
scope.initializing = true;
|
||||
// Using LABjs, wait until all scripts are loaded before rendering panel
|
||||
var scripts = $LAB.script("common/lib/d3.v3.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/lib/topojson.v1.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/lib/node-geohash.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/lib/d3.hexbin.v0.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/lib/queue.v1.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/display/binning.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/display/geopoints.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/display/bullseye.js?rand="+Math.floor(Math.random()*10000));
|
||||
|
||||
// Populate element. Note that jvectormap appends, does not replace.
|
||||
scripts.wait(function () {
|
||||
|
||||
queue()
|
||||
.defer(d3.json, "panels/map2/lib/world-110m.json")
|
||||
.defer(d3.tsv, "panels/map2/lib/world-country-names.tsv")
|
||||
.await(function(error, world, names) {
|
||||
dr.worldData = world;
|
||||
dr.worldNames = names;
|
||||
|
||||
//Better way to get these values? Seems kludgy to use jQuery on the div...
|
||||
var width = $(elem[0]).width(),
|
||||
height = $(elem[0]).height();
|
||||
|
||||
//scale to whichever dimension is smaller, helps to ensure the whole map is displayed
|
||||
dr.scale = (width > height) ? (height/5) : (width/5);
|
||||
|
||||
dr.zoom = d3.behavior.zoom()
|
||||
.scaleExtent([1, 20])
|
||||
.on("zoom", translate_map);
|
||||
|
||||
//used by choropleth
|
||||
//@todo change domain so that it reflects the domain of the data
|
||||
dr.quantize = d3.scale.quantize()
|
||||
.domain([0, 1000])
|
||||
.range(d3.range(9).map(function(i) { return "q" + (i+1); }));
|
||||
|
||||
//Extract name and two-letter codes for our countries
|
||||
dr.countries = topojson.feature(dr.worldData, dr.worldData.objects.countries).features;
|
||||
|
||||
dr.countries = dr.countries.filter(function(d) {
|
||||
return dr.worldNames.some(function(n) {
|
||||
if (d.id == n.id) {
|
||||
d.name = n.name;
|
||||
return d.short = n.short;
|
||||
}
|
||||
});
|
||||
}).sort(function(a, b) {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
//create the new svg
|
||||
dr.svg = d3.select(elem[0]).append("svg")
|
||||
.attr("width", "100%")
|
||||
.attr("height", "100%")
|
||||
.attr("viewBox", "0 0 " + width + " " + height)
|
||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
|
||||
.call(dr.zoom);
|
||||
dr.g = dr.svg.append("g");
|
||||
|
||||
scope.initializing = false;
|
||||
render_panel();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render updates to the SVG. Typically happens when the data changes (time, query)
|
||||
* or when new options are selected
|
||||
*/
|
||||
function render_panel() {
|
||||
|
||||
var width = $(elem[0]).width(),
|
||||
height = $(elem[0]).height();
|
||||
|
||||
//Projection is dependant on the map-type
|
||||
if (scope.panel.display.data.type === 'mercator') {
|
||||
dr.projection = d3.geo.mercator()
|
||||
.translate([width/2, height/2])
|
||||
.scale(dr.scale);
|
||||
|
||||
} else if (scope.panel.display.data.type === 'orthographic') {
|
||||
dr.projection = d3.geo.orthographic()
|
||||
.translate([width/2, height/2])
|
||||
.scale(100)
|
||||
.clipAngle(90);
|
||||
|
||||
//recenters the sphere more towards the US...not really necessary
|
||||
dr.projection.rotate([100 / 2, 20 / 2, dr.projection.rotate()[2]]);
|
||||
|
||||
}
|
||||
|
||||
dr.path = d3.geo.path()
|
||||
.projection(dr.projection).pointRadius(0.2);
|
||||
|
||||
console.log(scope.data);
|
||||
|
||||
//Geocoded points are decoded into lonlat
|
||||
dr.points = _.map(scope.data, function (k, v) {
|
||||
//console.log(k,v);
|
||||
var decoded = geohash.decode(v);
|
||||
return [decoded.longitude, decoded.latitude];
|
||||
});
|
||||
|
||||
//And also projected projected to x/y. Both sets of points are used
|
||||
//by different functions
|
||||
dr.projectedPoints = _.map(dr.points, function (coords) {
|
||||
return dr.projection(coords);
|
||||
});
|
||||
|
||||
dr.svg.select(".overlay").remove();
|
||||
|
||||
dr.svg.append("rect")
|
||||
.attr("class", "overlay")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
|
||||
//Draw the countries, if this is a choropleth, draw with fancy colors
|
||||
var countryPath = dr.g.selectAll(".land")
|
||||
.data(dr.countries);
|
||||
|
||||
countryPath.enter().append("path")
|
||||
.attr("class", function(d) {
|
||||
if (scope.panel.display.choropleth.enabled) {
|
||||
return 'land ' + dr.quantize(scope.data[d.short]);
|
||||
} else {
|
||||
return 'land';
|
||||
}
|
||||
})
|
||||
.attr("d", dr.path);
|
||||
|
||||
countryPath.exit().remove();
|
||||
|
||||
//If this is a sphere, set up drag and keypress listeners
|
||||
if (scope.panel.display.data.type === 'orthographic') {
|
||||
dr.svg.style("cursor", "move")
|
||||
.call(d3.behavior.drag()
|
||||
.origin(function() { var rotate = dr.projection.rotate(); return {x: 2 * rotate[0], y: -2 * rotate[1]}; })
|
||||
.on("drag", function() {
|
||||
if (scope.keylistener.keyActive(17)) {
|
||||
dr.projection.rotate([d3.event.x / 2, -d3.event.y / 2, dr.projection.rotate()[2]]);
|
||||
|
||||
//dr.svg.selectAll("path").attr("d", dr.path);
|
||||
dr.g.selectAll("path").attr("d", dr.path);
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Special fix for when the user changes from mercator -> orthographic
|
||||
//The globe won't redraw automatically, we need to force it
|
||||
if (scope.panel.display.data.type === 'orthographic') {
|
||||
dr.svg.selectAll("path").attr("d", dr.path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display option rendering
|
||||
* Order is important to render order here!
|
||||
*/
|
||||
|
||||
//@todo fix this
|
||||
var dimensions = [width, height];
|
||||
displayBinning(scope, dr, dimensions);
|
||||
displayGeopoints(scope, dr);
|
||||
displayBullseye(scope, dr);
|
||||
|
||||
|
||||
|
||||
|
||||
//If the panel scale is not default (e.g. the user has moved the maps around)
|
||||
//set the scale and position to the last saved config
|
||||
if (scope.panel.display.scale != -1) {
|
||||
dr.zoom.scale(scope.panel.display.scale).translate(scope.panel.display.translate);
|
||||
dr.g.style("stroke-width", 1 / scope.panel.display.scale).attr("transform", "translate(" + scope.panel.display.translate + ") scale(" + scope.panel.display.scale + ")");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On D3 zoom events, pan/zoom the map
|
||||
* Only applies if the ctrl-key is not pressed, so it doesn't clobber
|
||||
* sphere dragging
|
||||
*/
|
||||
function translate_map() {
|
||||
|
||||
var width = $(elem[0]).width(),
|
||||
height = $(elem[0]).height();
|
||||
|
||||
if (! scope.keylistener.keyActive(17)) {
|
||||
var t = d3.event.translate,
|
||||
s = d3.event.scale;
|
||||
t[0] = Math.min(width / 2 * (s - 1), Math.max(width / 2 * (1 - s), t[0]));
|
||||
t[1] = Math.min(height / 2 * (s - 1) + 230 * s, Math.max(height / 2 * (1 - s) - 230 * s, t[1]));
|
||||
dr.zoom.translate(t);
|
||||
|
||||
scope.panel.display.translate = t;
|
||||
scope.panel.display.scale = s;
|
||||
dr.g.style("stroke-width", 1 / s).attr("transform", "translate(" + t + ") scale(" + s + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
Loading…
Reference in New Issue
Block a user