dashboard
Version:
Create dashboards with gadgets on node.js
359 lines (298 loc) • 12.8 kB
HTML
<!-- name_resolve.xml -->
<!-- Author: Ian Smith (imsmith@uw.edu) -->
<html lang="en">
<meta http-equiv="Pragma" content="no-cache">
<head>
<title>SkyView</title>
<!-- ASCOT Basic Style Sheets -->
<link href="/css/960/reset.css" rel="stylesheet" type="text/css">
<link href="/css/960/text.css" rel="stylesheet" type="text/css">
<script src="/js/astroObjectLib.js" type="text/javascript"></script>
<script src="http://google.com/jsapi?key=ABQIAAAAVGHgv2pouycqhAw5tCmtChT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSq6qELjXXLwllm-seMw-iKrnLcNQ" type="text/javascript"></script>
<script type="text/javascript">
var skyView = null;
var ge;
google.load("earth", "1");
function SkyView() {
var self = new Object();
// Properties
var dataSetList;
var viewportBounds;
var flySpeed = 1.0;
var longitude = 0;
var latitude = 0;
gadget.saveState = function(){
return {
'longitude': longitude,
'latitude': latitude,
'flySpeed': flySpeed,
'viewportBounds': viewportBounds
}
};
gadget.loadState = function(state){
longitude = state.longitude;
latitude = state.latitude;
flySpeed = state.flySpeed;
//setTimeout(function(){
// gadget.dashboard.trigger("centerOfCoordinatesChanged");
// }, 200);
};
gadget.dashboard.bind('centerOfCoordinatesChanged', moveMap);
gadget.dashboard.bind('dataSetChanged', redrawAllDatasets);
gadget.dashboard.bind('dataSetListChanged', redrawAllDatasets);
gadget.dashboard.bindToGadget("nameResolver","viewportSpeed", setFlyToSpeed);
// CONSTANTS
var TIMER_VIEWCHANGEEND = 200; // ms to wait to trigger the ge viewchangeend event
google.earth.createInstance('content', successInit, failInit);
// callback on successful creation of ge plugin instance
function successInit(instance) {
ge = instance;
ge.getWindow().setVisibility(true);
ge.getOptions().setMapType(ge.MAP_TYPE_SKY);
ge.getNavigationControl().setVisibility(ge.VISIBILITY_AUTO);
ge.getOptions().setStatusBarVisibility(true);
gadget.inflateState();
// Add event listeners
google.earth.addEventListener(ge.getView(), "viewchangebegin", initCenterOfCoordinates);
}
var initCenterOfCoordinates = function() {
moveMap();
google.earth.removeEventListener(ge.getView(), "viewchangebegin", initCenterOfCoordinates);
// write the new VP bounds to the public variable
// TODO: This will need a timer, because the viewchangeend event fires so often when dragging slowly.
// We need to make sure that we arent writing the current bounds more often than once every 250ms or so
google.earth.addEventListener(ge.getView(), "viewchangeend", writeCurrentBounds);
}
function failInit(errorCode) {
alert("*** Error initializing google earth plugin ***");
}
// private Point List
// first make the list item constructor
function KMLListItem(){}
KMLListItem.prototype = {
KMLobj : null,
listItemId : -1,
isPlotted : false,
dataset: ""
};
var _KMLPointList = [];
var tidsViewchangeend = []; // array of timer IDs for ge viewchangeend event
var _registeredDatasets = [];
// accepts a list of dataset names and replots all points from the datasets
function redrawAllDatasets() {
clearKML();
var list = gadget.dashboard.getDataSetList();
for (var i = 0; i < list.length; i++){
plotDataset(list[i]);
}
}
// METHODS
// Sets the flytospeed between 0 and 5
function setFlyToSpeed() {
var speed = parseFloat(flySpeed);
if (!isNaN(speed)) {
if ((speed >= 0) && (speed <= 5)) {
ge.getOptions().setFlyToSpeed(speed); // fastest speed before ge.SPEED_TELEPORT
}
}
}
// Slews map to point (center) at new coordinate
// TODO: with range? or bounding box?
function moveMap(coords){
if(coords){
longitude = coords.getLongitude();
latitude = coords.getLatitude();
}
// check that ra and dec are numbers
if (!isNaN(longitude) && !isNaN(latitude)){
var lookAt = ge.createLookAt('');
lookAt.setLatitude(latitude);
lookAt.setLongitude(longitude);
lookAt.setAltitude(0);
lookAt.setHeading(0);
lookAt.setRange(7000.0);
ge.getView().setAbstractView(lookAt);
}
}
// Writes the current viewport bounds to a public variable.
// Uses a timer to prevent too many updates per second
// "Viewport_Current_Bounds" is a 2-element array of CelestialCoordinates. [topleft, bottomright]
// This function is called everytime viewport is moved (by attaching to the ge move event)
writeCurrentBounds = function(){
// we need to wait a few ms so we don't trigger this event too often
if (tidsViewchangeend.length !== 0){
// if the timer was already set, then clear them to reset them.
clearTimerArray(tidsViewchangeend);
}
// now there is no timer set
// so make one
var tid = setTimeout(function(){
boxBounds = ge.getView().getViewportGlobeBounds();
var lookAt = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND);
latitude = lookAt.getLatitude();
longitude = lookAt.getLongitude();
topLeft = new UW.astro.CelestialCoordinate(0,0);
topLeft.setLongitude(boxBounds.getWest());
topLeft.setLatitude(boxBounds.getNorth());
bottomRight = new UW.astro.CelestialCoordinate(0,0);
bottomRight.setLongitude(boxBounds.getEast());
bottomRight.setLatitude(boxBounds.getSouth());
curBounds = [topLeft, bottomRight]; // 2-element array of CelestialCoordinates. [topLeft, bottomRight]
gadget.dashboard.trigger('viewBoundsChanged',curBounds);
}, TIMER_VIEWCHANGEEND);
// add the new timer id to the array
tidsViewchangeend.push(tid);
}
// KML
// Clears all the KML from ge by removing every child.
function clearKML() {
if (ge !== null){
var features = ge.getFeatures();
while (features.getFirstChild()) {
features.removeChild(features.getFirstChild());
}
}
}
// Creates a KML object on ge for each "text" KML oject in "KML_List"
function showKML() {
var kmlList = di.readVariable(UW.astro.DEFAULT_NAMESPACE, "KML_List");
if (kmlList !== null) {
if (kmlList.length === 0){
//clearKML();
}
for (var i=0, len=kmlList.length; i<len; i++) {
parsed = ge.parseKml(kmlList[i]);
if (parsed !== null){
// TODO: better test for ge
if (ge !== null){
ge.getFeatures().appendChild(parsed);
}
}
}
}
}
// creates a point on ge for each CelestialCoordinate in the dataset
function plotDataset(dsName) {
var ds = gadget.dashboard.getDataSet(dsName);
if (!ds.isVisible()) {
return;
}
var pubDataset = ds.toJSON();
var toPlotStrings = [];
for (var i=0, len=pubDataset.length; i<len; i++) {
if (pubDataset[i].hasOwnProperty("db_CelestialCoord") && pubDataset[i].db_visible) { // check the visible property of the record
var cc = pubDataset[i].db_CelestialCoord;
toPlotStrings.push(cc.getKML());
}
}
// PLOT the kml objects in toPlot
if (ge !== null){
var geFeatures = ge.getFeatures(); // speed up the getFeatures methods
for (var i=0,len=toPlotStrings.length; i<len; i++){
parsed = ge.parseKml(toPlotStrings[i]);
geFeatures.appendChild(parsed);
// THIS WORKS - It's possible to modify a KML object after it's been appended
//parsed.setDescription("MODIFIED");
}
}
}
//
// this funciton does all the work plotting points on ge
function refreshKMLFromList(pubListName, privList) {
// Sync the pub and priv lists
var pubList = di.readVariable(UW.astro.DEFAULT_NAMESPACE, pubListName);
var toPlot = []; // array of ids to plot
var toRemove = []; // array of ids to remove
// compare the ids from pubList to the ids in the privList
// first find points to remove
// TODO: Is there a faster way to search these arrays?
// loop thru privList looking for points NOT in pubList
// loop backwards so we can splice array in loop
for (var i=privList.length-1; i>=0; i--) {
if ((pubList.getItemById(privList[i].listItemId) === null) || (pubList.isIdModified(privList[i].listItemId))) {
// has been removed from the pubList, so add it to the toRemove list
// and remove it from the privList
toRemove.push(privList[i].KMLobj); // add the KMLobj to the remove list
privList.splice(i,1); // remove it from privList
}
}
// TODO: check isPlotted!
// next find the new points to plot
// loop thru pub list looking for points NOT in priv list (they are new points)
for (var i=0, len=pubList.getLength(); i<len; i++){
var pubItemId = pubList.getIdByIndex(i);
var found = false;
// check for this id in the priv list
for (var i2=0, len2=privList.length; i2<len2; i2++){
if (privList[i2].listItemId === pubItemId) {
found = true;
//break;
// break actually breaks out of both for's, so lets just reset i=len
// TODO: CHANGE THIS BAD FORM
i2 = len;
}
}
if (!found){
// we found a NEW point in the pubList (not in privList)
// add it to the toPlot array
toPlot.push(pubItemId)
}
}
// Find indexes of modified points
var modifiedIdsList = pubList.getModifiedIds();
for (var i=0, len=modifiedIdsList.length; i<len; i++){
// toPlot.push(modifiedIdsList[i]);
pubList.setModifiedById(modifiedIdsList[i]);
}
// sync the GE to the priv list
// TODO: better test for GE
if (ge !== null){
var geFeatures = ge.getFeatures(); // speed up the getFeatures methods
// REMOVE the kmlobjects in toRemove
for (var i=0,len=toRemove.length; i<len; i++){
geFeatures.removeChild(toRemove[i]);
}
// PLOT the kml objects in toPlot
for (var i=0,len=toPlot.length; i<len; i++){
// first we plot it
var kmlText = pubList.getItemByIndex(toPlot[i]).getKML();
parsed = ge.parseKml(kmlText);
geFeatures.appendChild(parsed);
// then add it to the privList
var privItem = new KMLListItem();
privItem.KMLobj = parsed;
privItem.listItemId = toPlot[i];
privItem.isPlotted = true;
privList.push(privItem);
}
}
}
// HELPER
function clearTimerArray(timers){
if (timers instanceof Array){
for (var i=0, len=timers.length; i<len; i++){
clearTimeout(timers.splice(i,1)); // splice returns the removed element
}
}
}
function arrayContains(arr, el) {
for (var i=0, len=arr.length; i<len; i++) {
if (arr[i] === el) {
return true;
}
}
return false;
}
return self;
};
function init(){
skyView = new SkyView();
};
google.setOnLoadCallback(init);
</script>
</head>
<body>
<div id="content" style="width: 100%; height: 600px"></div>
</body>
</html>