dashboard
Version:
Create dashboards with gadgets on node.js
474 lines (395 loc) • 16.2 kB
text/xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- get_data.xml -->
<!-- Author: Ian Smith (imsmith@uw.edu) -->
<Module>
<ModulePrefs title="Plot">
<Require feature="locked-domain" />
<Require feature="dynamic-height"/>
<Require feature="opensocial-0.9"/>
<Require feature="minimessage"/>
<Require feature="settitle"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<link href="css/gadget.css" rel="stylesheet" type="text/css">
<script src="js/DataInterface.js" type="text/javascript"></script>
<script src="js/astroObjectLib.js" type="text/javascript"></script>
<script src="js/dataset.js" type="text/javascript"></script>
<div id="divQuery" style="width: 100%;">
Dataset Name: <input id="txtDatasetName" type="text" />
<div id="divStatusText" class="statusBox"></div>
</div>
<div id="divVPBounds" style="float:right;" class="infoBox">
<h3>Viewport Bounds</h3>
<span id="spViewportBounds" class="info"></span>
</div>
<div id="divQueryButtons">
</div>
<div id="divCatalog">
Catalog: <select id="selCatalog">
</select>
</div>
<div id="divQueryBox" style="width:100%;">
Query String:
<br/>
<textarea id="txtQueryString" rows="5" style="width:100%;"></textarea>
<br/>
<input id="btGetData" onclick="ga.getData();" type="button" value="Submit"/>
</div>
<script type="text/javascript">
var ga = null,
DEBUG = false;
function debugLog(msg){ if(DEBUG){UW.astro.debugLog(GADGET_NAME + ": " + msg);}}
// GLOBAL CONSTANTS
var GADGET_NAME = "Get_Data" + "_" + Math.floor(Math.random()*100000).toString();
// Text in {{ }} such as " {{ra.lower}}" are substituted in setQueryText() method
var QUERY_BUTTONS = [ { buttonNum: 0,
name: "SDSS Stars",
desc: "Get star magnitudes in U, G, R, I, Z from SDSS",
catalog: "SDSS",
query: "SELECT TOP 500 objid, ra, dec, modelMag_u, modelMag_g, modelMag_r, modelMag_i, modelMag_z, (modelMag_u - modelMag_g) as u_g, (modelMag_g - modelMag_r) as g_r, (modelMag_r - modelMag_i) as r_i, (modelMag_i - modelMag_z) as i_z from Star where ra between {{ra.lower}} and {{ra.upper}} and dec between {{dec.lower}} and {{dec.upper}} and modelMag_g > -9999 ORDER BY modelMag_g ASC"
},
{ buttonNum: 1,
name: "SDSS Galaxies",
desc: "Get galaxy magnitudes in U, G, R, I, Z from SDSS",
catalog: "SDSS",
query: "SELECT TOP 500 g.objid, g.ra, g.dec, s.z, g.modelMag_u, g.modelMag_g, g.modelMag_r, g.modelMag_i, g.modelMag_z, (g.modelMag_u - g.modelMag_g) as u_g, (g.modelMag_g - g.modelMag_r) as g_r, (g.modelMag_r - g.modelMag_i) as r_i, (g.modelMag_i - g.modelMag_z) as i_z from Galaxy as g left outer join SpecObjAll as s on g.specobjID = s.specobjID where g.ra between {{ra.lower}} and {{ra.upper}} and g.dec between {{dec.lower}} and {{dec.upper}} and g.modelMag_g > -9999 ORDER BY g.modelMag_g ASC"
}];
//
// { buttonNum: 2,
// name: "2MASS 1",
// desc: "2MASS 1",
// catalog: "2MASS",
// query: "Under Construction"
// }
// ];
//
// create HR object
function init(){
gadgets.window.setTitle("Data Query");
ga = new GetData();
ga.setFields();
gadgets.window.adjustHeight();
}
function GetData(){
var my = new Object();
var _myFields = {};
// CONSTANTS
var PLOT_HEIGHT = 400,
PLOT_WIDTH = 300;
// Status Icons
var ICON_URL_SELECTED = '/ascot/gadgets/images/target_yellow.png',
ICON_URL_DEFAULT = '/ascot/gadgets/images/target.png',
ICON_URL_SPINNER = '/ascot/gadgets/images/spinnerGrey.gif',
ICON_URL_ERROR = '/ascot/gadgets/images/errorIcon.gif',
ICON_URL_SUCCESS = '/ascot/gadgets/images/successIcon.gif';
var ICON = { SUCCESS : ICON_URL_SUCCESS,
ERROR : ICON_URL_ERROR,
SPINNER : ICON_URL_SPINNER,
NONE : ""}
// PRIVATE
var _namespaceList = [ UW.astro.DEFAULT_NAMESPACE ]; // list of our current Namespaces. Just init with the default
var _catalogs = [ { name: "SDSS", url: "http://cas.sdss.org/public/en/tools/search/x_sql.asp" }, // contains info for catalogs and thier urls
// { name: "2MASS", url: "" }
];
// Private Helper Variables
var di = new UW.astro.DataInterface(GADGET_NAME); // make dataInterface object, init with default
// INIT
di.registerMe( { namespaceList : _namespaceList,
variableList : [ "Dataset_List", "Viewport_Current_Bounds" ],
triggerList : [ [ "Viewport_Current_Bounds", setVPBounds] ],
} );
function getDatasetNameText () {
return document.getElementById("txtDatasetName").value;
}
function clearForm() {
document.getElementById("txtDatasetName").value = '';
// no reason to clear query string yet
// document.getElementById("txtQueryString").value = '';
}
// PUBLIC METHODS
my.setFields = function() {
// set the catalog options
var options = [];
for (var i=0, len=_catalogs.length; i<len; i++) {
options.push(_catalogs[i].name);
}
setSelectOptions("selCatalog", options);
// create the buttons
for (var i=0, len=QUERY_BUTTONS.length; i<len; i++) {
createQueryButton(QUERY_BUTTONS[i]);
}
}
function createQueryButton(buttonObj) {
var divButtons = document.getElementById('divQueryButtons');
var button = document.createElement('input');
button.setAttribute('type', 'button');
button.setAttribute('name', buttonObj.name);
button.setAttribute('value', buttonObj.name);
button.setAttribute('title', buttonObj.desc);
button.onclick = function(){ ga.setQueryText(buttonObj.buttonNum); };
divButtons.appendChild(button);
}
my.getData = function() {
var dsName = getDatasetNameText();
if (dsName.length < 1) {
showError("Enter dataset name");
return;
}
// TODO: other ways to choose the bounds we want on the gadget
showSpinner("Getting objects...");
// get query string from the text area
var queryObj = {data: {cmd:null, format:null}, url: null};
queryObj.data.cmd = getQueryString();
if (queryObj.data.cmd === "") {
showError('Enter query string');
return;
}
// find catalog in the _catalogs object to get the url
var selectedCatalog = getSelectedOption("selCatalog");
for (var i=0, len=_catalogs.length; i<len; i++) {
if (_catalogs[i].name === selectedCatalog) {
queryObj.url = _catalogs[i].url;
}
}
// set to XML (for SDSS anyway)
queryObj.data.format = "xml";
if (queryObj.url === null) {
showError('Select a catalog');
return;
}
// finishes with callback "queryResponseCB"
makeGETRequest(queryObj.url, queryObj.data, queryResponseCB);
}
my.setQueryText = function(buttonNum) {
if (QUERY_BUTTONS.length > buttonNum) {
// set catalog
var buttonObj = QUERY_BUTTONS[buttonNum];
setSelectedCatalog(buttonObj.catalog);
var qString = buttonObj.query;
// replace bounds
var bounds = getVPBounds();
if (bounds !== null) {
qString = replaceQueryVars(qString, "{{ra.lower}}", bounds[0].getRa().toFixed(6));
qString = replaceQueryVars(qString, "{{ra.upper}}", bounds[1].getRa().toFixed(6));
qString = replaceQueryVars(qString, "{{dec.lower}}", bounds[1].getDec().toFixed(6));
qString = replaceQueryVars(qString, "{{dec.upper}}", bounds[0].getDec().toFixed(6));
}
setQueryString(qString);
}
}
function replaceQueryVars(str, replacee, replacer) {
return str.replace(replacee, replacer);
}
function getVPBounds() {
// get current VP bounds
// bounds is array of CelestialCoordinates: [topLeft, bottomRight]
return di.readVariable(UW.astro.DEFAULT_NAMESPACE, "Viewport_Current_Bounds");
}
function makeGETRequest(url, data, callback) {
var params = {};
getdata = gadgets.io.encodeValues(data);
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
url = url + '?' + getdata;
gadgets.io.makeRequest(url, callback, params);
}
function queryResponseCB(obj) {
// parse the XML
if (obj.errors.length > 0){
// errors
debugLog(obj.errors);
if (obj.errors[0].indexOf("504") !== -1) {
showError("Request Timed out.<br/>Try restricting search to<br/>smaller ra/dec bounds.");
} else {
showError('Service: ' + obj.errors);
}
return;
}
else if (obj.text === ""){
// returned empty string
showError('Service returned empty string');
return;
}
xmlDoc = xmlStringToDoc(obj.text);
// walk XML to create points and write to objectData
var rows = xmlDoc.getElementsByTagName('Row');
if ((rows.length === 0) || ((rows.length === 1) && (rows[0].textContent.indexOf('No rows returned') !== -1))){
// the special case answer is that no rows were returned
showError('No objects from ' + getSelectedOption("selCatalog") + ' catalog');
return;
}
// indicate status to user
showSuccess("Returned " + rows.length + " records.");
// We probably have valid data at this point, so parse it and display it
// create and write Dataset from the row data
var ds = createDataset(rows);
ds.setName(getDatasetNameText());
writeDataset(ds);
}
function arrayContains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
function writeDataset(ds) {
// TODO: this needs to be redone with di functions like: di.getDataset_List, di.addDataset
// write dataset list
var list = di.readVariable(UW.astro.DEFAULT_NAMESPACE, "Dataset_List");
if (list === null) {
list = [];
}
var name = ds.getName();
if (!arrayContains(list, name)) {
di.registerVariable(name, null);
di.writeVariable(UW.astro.DEFAULT_NAMESPACE, name, ds);
list.push(name);
di.writeVariable(UW.astro.DEFAULT_NAMESPACE, "Dataset_List", list);
}
else {
// write dataset
di.writeVariable(UW.astro.DEFAULT_NAMESPACE, name, ds);
}
}
// Accepts "rows" as an ObjectHTML collection
// and creates a Dataset from it and returns it
function createDataset(rows) {
var json = [];
for (var i=0,len=rows.length; i<len; i++){
var row = rows[i];
var elem = {};
// loop through attributes
for (var k=0, kLen=row.attributes.length; k<kLen; k++){
// k is the attribute index
var attName = row.attributes[k].nodeName;
var attValue = row.attributes[k].nodeValue;
elem[attName] = attValue;
}
json.push(elem);
}
// create dataset
ds = new UW.astro.Dataset(json);
return ds;
}
// HELPER
function clearStatus() {
showStatus(ICON.NONE, "");
}
function showSpinner(text) {
showStatus(ICON.SPINNER, text);
}
function showSuccess(text) {
showStatus(ICON.SUCCESS, text);
}
function showError(text) {
showStatus(ICON.ERROR, text);
}
function showStatus(iconUrl, text){
if (iconUrl !== ICON.NONE) {
setStatus( '<img id="imgStatus" src="' + iconUrl + '" /> ' + text);
} else {
setStatus(text);
}
}
function setStatus(text) {
// set text status
var statusDiv = document.getElementById('divStatusText');
statusDiv.innerHTML = text;
// make visible
statusDiv.style.visibility = 'block';
}
function setVPBounds() {
var bounds = getVPBounds();
if (bounds !== null) {
getField('spViewportBounds').innerHTML = "ra between " + bounds[0].getRa().toFixed(4) + " and " + bounds[1].getRa().toFixed(4) + " and<br/>dec between " + bounds[1].getDec().toFixed(4) + " and " + bounds[0].getDec().toFixed(4);
}
}
function xmlStringToDoc(text){
if (window.DOMParser){
parser=new DOMParser();
xmlDoc=parser.parseFromString(text,"text/xml");
}
else // Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(text);
}
// TODO: test to verify its created
return xmlDoc;
}
// HTML Field Getters/Setters
function getField(field) {
if (!(_myFields.hasOwnProperty(field)) || (_myFields[field] === null)) {
_myFields[field] = document.getElementById(field);
}
return _myFields[field];
}
function getQueryString() {
return getField("txtQueryString").value;
}
function setQueryString(str) {
setTextBoxValue("txtQueryString", str);
}
function setSelectedCatalog(catalog) {
selectValue("selCatalog", catalog);
}
function restrictVPBounds() {
return getField('ckVPBounds').checked;
}
function setTextBoxValue(textBoxName, value) {
textBox = document.getElementById(textBoxName);
if (textBox !== null && textBox !== undefined) {
textBox.value = value;
}
}
// accepts name of select box
// returns the value in the select box, or ""
function getSelectedOption(select) {
var selName = document.getElementById(select);
if (selName.length > 0){
return selName.options[selName.selectedIndex].value;
} else {
return "";
}
}
function selectValue(selectName, value) {
var sel = document.getElementById(selectName);
if (sel === undefined || sel === null) {
return;
}
for (var i=0, len=sel.options.length; i<len; i++) {
if (sel.options[i].value === value) {
sel.options[i].selected = true;
return;
}
}
}
// Accepts the name of a select object, and an array of strings
// replaces the options with the array of strings
function setSelectOptions(selectName, options) {
var select = document.getElementById(selectName);
if (select === null) {
return;
}
// save old selected option so maybe it can be reselected
var oldOpt = getSelectedOption(selectName);
// clear options
for (var i=select.length-1; i>=0; i--) {
select.remove(i);
}
// add options
for (var i=0, len=options.length; i<len; i++) {
// if oldOption is in the list, then select it
select.add(new Option(options[i], options[i], false, (oldOpt === options[i])), null);
}
}
return my;
}
gadgets.util.registerOnLoadHandler(init);
</script>
]]>
</Content>
</Module>