Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
7dc708d5
Commit
7dc708d5
authored
Apr 18, 2013
by
Zachary Tong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update tab spacing
parent
35c59fd4
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
416 additions
and
416 deletions
+416
-416
panels/map2/module.js
+416
-416
No files found.
panels/map2/module.js
View file @
7dc708d5
angular
.
module
(
'kibana.map2'
,
[])
angular
.
module
(
'kibana.map2'
,
[])
.
controller
(
'map2'
,
function
(
$scope
,
eventBus
,
keylistener
)
{
.
controller
(
'map2'
,
function
(
$scope
,
eventBus
,
keylistener
)
{
// Set and populate defaults
// Set and populate defaults
var
_d
=
{
var
_d
=
{
query
:
"*"
,
query
:
"*"
,
map
:
"world"
,
map
:
"world"
,
colors
:
[
'#C8EEFF'
,
'#0071A4'
],
colors
:
[
'#C8EEFF'
,
'#0071A4'
],
size
:
100
,
size
:
100
,
exclude
:
[],
exclude
:
[],
spyable
:
true
,
spyable
:
true
,
group
:
"default"
,
group
:
"default"
,
index_limit
:
0
,
index_limit
:
0
,
display
:
{
display
:
{
translate
:[
0
,
0
],
translate
:[
0
,
0
],
scale
:
-
1
,
scale
:
-
1
,
data
:
{
data
:
{
samples
:
1000
,
samples
:
1000
,
type
:
"mercator"
type
:
"mercator"
},
},
geopoints
:
{
geopoints
:
{
enabled
:
false
,
enabled
:
false
,
enabledText
:
"Enabled"
,
enabledText
:
"Enabled"
,
pointSize
:
0.3
,
pointSize
:
0.3
,
pointAlpha
:
0.6
pointAlpha
:
0.6
},
},
binning
:
{
binning
:
{
enabled
:
false
,
enabled
:
false
,
hexagonSize
:
2
,
hexagonSize
:
2
,
hexagonAlpha
:
1.0
,
hexagonAlpha
:
1.0
,
areaEncoding
:
true
,
areaEncoding
:
true
,
areaEncodingField
:
"primary"
,
areaEncodingField
:
"primary"
,
colorEncoding
:
true
,
colorEncoding
:
true
,
colorEncodingField
:
"primary"
colorEncodingField
:
"primary"
},
},
choropleth
:
{
choropleth
:
{
enabled
:
false
enabled
:
false
},
},
bullseye
:
{
bullseye
:
{
enabled
:
false
,
enabled
:
false
,
coord
:
{
coord
:
{
lat
:
0
,
lat
:
0
,
lon
:
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
.
get_data
=
function
()
{
// Make sure we have everything for the request to complete
if
(
_
.
isUndefined
(
$scope
.
panel
.
index
)
||
_
.
isUndefined
(
$scope
.
time
))
return
$scope
.
panel
.
loading
=
true
;
var
request
=
$scope
.
ejs
.
Request
().
indices
(
$scope
.
panel
.
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
.
panel
.
index
+
"/_search?pretty -d'
\
n"
+
angular
.
toJson
(
JSON
.
parse
(
request
.
toString
()),
true
)
+
"'</pre>"
}
};
function
set_time
(
time
)
{
$scope
.
time
=
time
;
$scope
.
panel
.
index
=
_
.
isUndefined
(
time
.
index
)
?
$scope
.
panel
.
index
:
time
.
index
$scope
.
get_data
();
}
}
},
$scope
.
build_search
=
function
(
field
,
value
)
{
activeDisplayTab
:
"Geopoints"
$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
);
_
.
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
.
get_data
=
function
()
{
// Make sure we have everything for the request to complete
if
(
_
.
isUndefined
(
$scope
.
panel
.
index
)
||
_
.
isUndefined
(
$scope
.
time
))
return
$scope
.
panel
.
loading
=
true
;
var
request
=
$scope
.
ejs
.
Request
().
indices
(
$scope
.
panel
.
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
.
panel
.
index
+
"/_search?pretty -d'
\
n"
+
angular
.
toJson
(
JSON
.
parse
(
request
.
toString
()),
true
)
+
"'</pre>"
}
};
function
set_time
(
time
)
{
$scope
.
time
=
time
;
$scope
.
panel
.
index
=
_
.
isUndefined
(
time
.
index
)
?
$scope
.
panel
.
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
)
{
//elem.html('')
scope
.
initializing
=
false
;
scope
.
worldData
=
null
;
scope
.
worldNames
=
null
;
scope
.
ctrlKey
=
false
;
//These are various options that should not be cached in scope.panel
scope
.
options
=
{
data
:
{
dropdown
:[
{
"text"
:
"Mercator (Flat)"
,
id
:
"mercator"
},
{
text
:
"Orthographic (Sphere)"
,
id
:
"orthographic"
}
]
}
};
};
$scope
.
isActive
=
function
(
tab
)
{
return
(
tab
.
toLowerCase
()
===
$scope
.
panel
.
activeDisplayTab
.
toLowerCase
());
}
$scope
.
tabClick
=
function
(
tab
)
{
/**
$scope
.
panel
.
activeDisplayTab
=
tab
;
* Initialize the panels if new, or render existing panels
}
*/
scope
.
init_or_render
=
function
()
{
if
(
typeof
scope
.
svg
===
'undefined'
)
{
console
.
log
(
"init"
);
})
//prevent duplicate initialization steps, if render is called again
.
filter
(
'enabledText'
,
function
()
{
//before the svg is setup
return
function
(
value
)
{
if
(
!
scope
.
initializing
)
{
if
(
value
===
true
)
{
init_panel
();
return
"Enabled"
;
}
else
{
return
"Disabled"
;
}
}
}
}
else
{
})
console
.
log
(
"render"
);
.
directive
(
'map2'
,
function
()
{
render_panel
();
return
{
}
restrict
:
'A'
,
};
link
:
function
(
scope
,
elem
,
attrs
)
{
//elem.html('')
scope
.
initializing
=
false
;
scope
.
worldData
=
null
;
scope
.
worldNames
=
null
;
scope
.
ctrlKey
=
false
;
//These are various options that should not be cached in scope.panel
scope
.
options
=
{
data
:
{
dropdown
:[
{
"text"
:
"Mercator (Flat)"
,
id
:
"mercator"
},
{
text
:
"Orthographic (Sphere)"
,
id
:
"orthographic"
}
]
}
};
/**
* Initialize the panels if new, or render existing panels
*/
scope
.
init_or_render
=
function
()
{
if
(
typeof
scope
.
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
();
});
/**
/**
* Receive render events
* On window resize, re-render the panel
*/
*/
scope
.
$on
(
'render
'
,
function
()
{
angular
.
element
(
window
).
bind
(
'resize
'
,
function
()
{
scope
.
init_or_render
();
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
;
* Load the various panel-specific scripts, map data, then initialize
// Using LABjs, wait until all scripts are loaded before rendering panel
* the svg and set appropriate D3 settings
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
))
function
init_panel
()
{
.
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
));
scope
.
initializing
=
true
;
// Populate element. Note that jvectormap appends, does not replace.
// Using LABjs, wait until all scripts are loaded before rendering panel
scripts
.
wait
(
function
()
{
var
scripts
=
$LAB
.
script
(
"panels/map2/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.
queue
()
scripts
.
wait
(
function
()
{
.
defer
(
d3
.
json
,
"panels/map2/lib/world-110m.json"
)
.
defer
(
d3
.
tsv
,
"panels/map2/lib/world-country-names.tsv"
)
.
await
(
function
(
error
,
world
,
names
)
{
scope
.
worldData
=
world
;
scope
.
worldNames
=
names
;
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
)
{
scope
.
worldData
=
world
;
scope
.
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
();
//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
scope
.
scale
=
(
width
>
height
)
?
(
height
/
5
)
:
(
width
/
5
);
//scale to whichever dimension is smaller, helps to ensure the whole map is displayed
scope
.
scale
=
(
width
>
height
)
?
(
height
/
5
)
:
(
width
/
5
);
scope
.
zoom
=
d3
.
behavior
.
zoom
()
.
scaleExtent
([
1
,
8
])
.
on
(
"zoom"
,
translate_map
);
scope
.
zoom
=
d3
.
behavior
.
zoom
()
//used by choropleth
.
scaleExtent
([
1
,
8
])
//@todo change domain so that it reflects the domain of the data
.
on
(
"zoom"
,
translate_map
);
scope
.
quantize
=
d3
.
scale
.
quantize
()
.
domain
([
0
,
1000
])
.
range
(
d3
.
range
(
9
).
map
(
function
(
i
)
{
return
"q"
+
(
i
+
1
);
}));
//used by choropleth
//@todo change domain so that it reflects the domain of the data
scope
.
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
scope
.
countries
=
topojson
.
feature
(
scope
.
worldData
,
scope
.
worldData
.
objects
.
countries
).
features
;
//Extract name and two-letter codes for our countries
scope
.
countries
=
scope
.
countries
.
filter
(
function
(
d
)
{
scope
.
countries
=
topojson
.
feature
(
scope
.
worldData
,
scope
.
worldData
.
objects
.
countries
).
features
;
return
scope
.
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
);
});
scope
.
countries
=
scope
.
countries
.
filter
(
function
(
d
)
{
return
scope
.
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
scope
.
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
(
scope
.
zoom
);
scope
.
g
=
scope
.
svg
.
append
(
"g"
);
//create the new svg
scope
.
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
(
scope
.
zoom
);
scope
.
g
=
scope
.
svg
.
append
(
"g"
);
scope
.
initializing
=
false
;
render_panel
();
});
});
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
(),
* Render updates to the SVG. Typically happens when the data changes (time, query)
height
=
$
(
elem
[
0
]).
height
();
* 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
//Projection is dependant on the map-type
if
(
scope
.
panel
.
display
.
data
.
type
===
'mercator'
)
{
if
(
scope
.
panel
.
display
.
data
.
type
===
'mercator'
)
{
scope
.
projection
=
d3
.
geo
.
mercator
()
scope
.
projection
=
d3
.
geo
.
mercator
()
.
translate
([
width
/
2
,
height
/
2
])
.
translate
([
width
/
2
,
height
/
2
])
.
scale
(
scope
.
scale
);
.
scale
(
scope
.
scale
);
}
else
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
}
else
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
scope
.
projection
=
d3
.
geo
.
orthographic
()
scope
.
projection
=
d3
.
geo
.
orthographic
()
.
translate
([
width
/
2
,
height
/
2
])
.
translate
([
width
/
2
,
height
/
2
])
.
scale
(
100
)
.
scale
(
100
)
.
clipAngle
(
90
);
.
clipAngle
(
90
);
//recenters the sphere more towards the US...not really necessary
//recenters the sphere more towards the US...not really necessary
scope
.
projection
.
rotate
([
100
/
2
,
20
/
2
,
scope
.
projection
.
rotate
()[
2
]]);
scope
.
projection
.
rotate
([
100
/
2
,
20
/
2
,
scope
.
projection
.
rotate
()[
2
]]);
}
}
var
path
=
d3
.
geo
.
path
()
var
path
=
d3
.
geo
.
path
()
.
projection
(
scope
.
projection
);
.
projection
(
scope
.
projection
);
//Special fix for when the user changes from mercator -> orthographic
//Special fix for when the user changes from mercator -> orthographic
//The globe won't redraw automatically, we need to force it
//The globe won't redraw automatically, we need to force it
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
scope
.
svg
.
selectAll
(
"path"
).
attr
(
"d"
,
path
);
scope
.
svg
.
selectAll
(
"path"
).
attr
(
"d"
,
path
);
}
}
console
.
log
(
scope
.
data
);
console
.
log
(
scope
.
data
);
//Geocoded points are decoded into lonlat
//Geocoded points are decoded into lonlat
scope
.
points
=
_
.
map
(
scope
.
data
,
function
(
k
,
v
)
{
scope
.
points
=
_
.
map
(
scope
.
data
,
function
(
k
,
v
)
{
//console.log(k,v);
//console.log(k,v);
var
decoded
=
geohash
.
decode
(
v
);
var
decoded
=
geohash
.
decode
(
v
);
return
[
decoded
.
longitude
,
decoded
.
latitude
];
return
[
decoded
.
longitude
,
decoded
.
latitude
];
});
});
//And also projected projected to x/y. Both sets of points are used
//And also projected projected to x/y. Both sets of points are used
//by different functions
//by different functions
scope
.
projectedPoints
=
_
.
map
(
scope
.
points
,
function
(
coords
)
{
scope
.
projectedPoints
=
_
.
map
(
scope
.
points
,
function
(
coords
)
{
return
scope
.
projection
(
coords
);
return
scope
.
projection
(
coords
);
});
});
scope
.
svg
.
select
(
".overlay"
).
remove
();
scope
.
svg
.
select
(
".overlay"
).
remove
();
scope
.
svg
.
append
(
"rect"
)
scope
.
svg
.
append
(
"rect"
)
.
attr
(
"class"
,
"overlay"
)
.
attr
(
"class"
,
"overlay"
)
.
attr
(
"width"
,
width
)
.
attr
(
"width"
,
width
)
.
attr
(
"height"
,
height
)
.
attr
(
"height"
,
height
)
.
attr
(
"transform"
,
"translate("
+
width
/
2
+
","
+
height
/
2
+
")"
);
.
attr
(
"transform"
,
"translate("
+
width
/
2
+
","
+
height
/
2
+
")"
);
//Draw the countries, if this is a choropleth, draw with fancy colors
//Draw the countries, if this is a choropleth, draw with fancy colors
var
countryPath
=
scope
.
g
.
selectAll
(
".land"
)
var
countryPath
=
scope
.
g
.
selectAll
(
".land"
)
.
data
(
scope
.
countries
);
.
data
(
scope
.
countries
);
countryPath
.
enter
().
append
(
"path"
)
countryPath
.
enter
().
append
(
"path"
)
.
attr
(
"class"
,
function
(
d
)
{
.
attr
(
"class"
,
function
(
d
)
{
if
(
scope
.
panel
.
display
.
choropleth
.
enabled
)
{
if
(
scope
.
panel
.
display
.
choropleth
.
enabled
)
{
return
'land '
+
scope
.
quantize
(
scope
.
data
[
d
.
short
]);
return
'land '
+
scope
.
quantize
(
scope
.
data
[
d
.
short
]);
}
else
{
}
else
{
return
'land'
;
return
'land'
;
}
}
})
})
.
attr
(
"d"
,
path
);
.
attr
(
"d"
,
path
);
countryPath
.
exit
().
remove
();
countryPath
.
exit
().
remove
();
/*
/*
//draw boundaries
//draw boundaries
scope.g.selectAll("land").append("path")
scope.g.selectAll("land").append("path")
.datum(topojson.mesh(scope.worldData, scope.worldData.objects.land, function(a, b) { return a !== b; }))
.datum(topojson.mesh(scope.worldData, scope.worldData.objects.land, function(a, b) { return a !== b; }))
.attr("class", "land boundary")
.attr("class", "land boundary")
.attr("d", path);
.attr("d", path);
*/
*/
//If this is a sphere, set up drag and keypress listeners
//If this is a sphere, set up drag and keypress listeners
//@todo implement a global "keypress service", since this fails if there are >1 spheres
//@todo implement a global "keypress service", since this fails if there are >1 spheres
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
if
(
scope
.
panel
.
display
.
data
.
type
===
'orthographic'
)
{
//scope.svg.focus();
//scope.svg.focus();
/*
/*
scope.svg.selectAll(".overlay")
scope.svg.selectAll(".overlay")
.on("keydown", function() {
.on("keydown", function() {
scope.ctrlKey = d3.event.ctrlKey;
scope.ctrlKey = d3.event.ctrlKey;
})
})
.on("keyup", function() {
.on("keyup", function() {
scope.ctrlKey = d3.event.ctrlKey;
scope.ctrlKey = d3.event.ctrlKey;
});
});
*/
*/
scope
.
svg
.
style
(
"cursor"
,
"move"
)
scope
.
svg
.
style
(
"cursor"
,
"move"
)
.
call
(
d3
.
behavior
.
drag
()
.
call
(
d3
.
behavior
.
drag
()
.
origin
(
function
()
{
var
rotate
=
scope
.
projection
.
rotate
();
return
{
x
:
2
*
rotate
[
0
],
y
:
-
2
*
rotate
[
1
]};
})
.
origin
(
function
()
{
var
rotate
=
scope
.
projection
.
rotate
();
return
{
x
:
2
*
rotate
[
0
],
y
:
-
2
*
rotate
[
1
]};
})
.
on
(
"drag"
,
function
()
{
.
on
(
"drag"
,
function
()
{
if
(
scope
.
ctrlKey
)
{
if
(
scope
.
ctrlKey
)
{
scope
.
projection
.
rotate
([
d3
.
event
.
x
/
2
,
-
d3
.
event
.
y
/
2
,
scope
.
projection
.
rotate
()[
2
]]);
scope
.
projection
.
rotate
([
d3
.
event
.
x
/
2
,
-
d3
.
event
.
y
/
2
,
scope
.
projection
.
rotate
()[
2
]]);
scope
.
svg
.
selectAll
(
"path"
).
attr
(
"d"
,
path
);
scope
.
svg
.
selectAll
(
"path"
).
attr
(
"d"
,
path
);
}
}
}));
}));
}
}
/**
/**
* Display option rendering
* Display option rendering
* Order is important to render order here!
* Order is important to render order here!
*/
*/
//@todo fix this
//@todo fix this
var
dimensions
=
[
width
,
height
];
var
dimensions
=
[
width
,
height
];
displayBinning
(
scope
,
dimensions
);
displayBinning
(
scope
,
dimensions
);
displayGeopoints
(
scope
,
path
);
displayGeopoints
(
scope
,
path
);
displayBullseye
(
scope
,
path
);
displayBullseye
(
scope
,
path
);
//If the panel scale is not default (e.g. the user has moved the maps around)
//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
//set the scale and position to the last saved config
if
(
scope
.
panel
.
display
.
scale
!=
-
1
)
{
if
(
scope
.
panel
.
display
.
scale
!=
-
1
)
{
scope
.
zoom
.
scale
(
scope
.
panel
.
display
.
scale
).
translate
(
scope
.
panel
.
display
.
translate
);
scope
.
zoom
.
scale
(
scope
.
panel
.
display
.
scale
).
translate
(
scope
.
panel
.
display
.
translate
);
scope
.
g
.
style
(
"stroke-width"
,
1
/
scope
.
panel
.
display
.
scale
).
attr
(
"transform"
,
"translate("
+
scope
.
panel
.
display
.
translate
+
") scale("
+
scope
.
panel
.
display
.
scale
+
")"
);
scope
.
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
* On D3 zoom events, pan/zoom the map
* Only applies if the ctrl-key is not pressed, so it doesn't clobber
* Only applies if the ctrl-key is not pressed, so it doesn't clobber
* sphere dragging
* sphere dragging
*/
*/
function
translate_map
()
{
function
translate_map
()
{
var
width
=
$
(
elem
[
0
]).
width
(),
var
width
=
$
(
elem
[
0
]).
width
(),
height
=
$
(
elem
[
0
]).
height
();
height
=
$
(
elem
[
0
]).
height
();
if
(
!
scope
.
ctrlKey
)
{
if
(
!
scope
.
ctrlKey
)
{
var
t
=
d3
.
event
.
translate
,
var
t
=
d3
.
event
.
translate
,
s
=
d3
.
event
.
scale
;
s
=
d3
.
event
.
scale
;
t
[
0
]
=
Math
.
min
(
width
/
2
*
(
s
-
1
),
Math
.
max
(
width
/
2
*
(
1
-
s
),
t
[
0
]));
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
]));
t
[
1
]
=
Math
.
min
(
height
/
2
*
(
s
-
1
)
+
230
*
s
,
Math
.
max
(
height
/
2
*
(
1
-
s
)
-
230
*
s
,
t
[
1
]));
scope
.
zoom
.
translate
(
t
);
scope
.
zoom
.
translate
(
t
);
scope
.
panel
.
display
.
translate
=
t
;
scope
.
panel
.
display
.
translate
=
t
;
scope
.
panel
.
display
.
scale
=
s
;
scope
.
panel
.
display
.
scale
=
s
;
scope
.
g
.
style
(
"stroke-width"
,
1
/
s
).
attr
(
"transform"
,
"translate("
+
t
+
") scale("
+
s
+
")"
);
scope
.
g
.
style
(
"stroke-width"
,
1
/
s
).
attr
(
"transform"
,
"translate("
+
t
+
") scale("
+
s
+
")"
);
}
}
}
}
}
}
};
};
});
});
\ No newline at end of file
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment