1
/*global Class, $, Option, document, $A, Event, Ajax, Element, Builder, Debug, UIElement */
2
var LayerManagerMenuEntry = Class.create(UIElement, {
6
initialize: function (layermanager, layer) {
7
this.className = "layerManagerMenuEntry";
8
this.layermanager = layermanager;
10
this.domNode = Builder.node('li', {className: 'accordionItem'});
12
// If layer is not set, create an empty "template" layer
13
if (layer.type === "NewLayer") {
14
this.displayNewLayerOptions();
16
else if (layer.type === "TileLayer") {
17
this.displayTileLayerOptions();
20
this.layermanager.accordionList.appendChild(this.domNode); //Cannot use prototype's insert() method to insert on top. Does not work in IE.
22
//Add tooltips (has to occur after dom-node has been appended)
23
if (layer.type === "TileLayer") {
24
this.layermanager.fire('newToolTip', {id: "#" + this.removeBtn.id, params: {position: 'topleft'}});
25
this.layermanager.fire('newToolTip', {id: "#" + this.visibilityBtn.id, params: {position: 'topleft'}});
31
* @method displayTileLayerOptions
33
displayTileLayerOptions: function () {
35
this.header = this.domNode.appendChild(this.createMenuRowHeader(this.layer));
36
this.content = this.domNode.appendChild(this.createMenuRowContent(this.layer));
39
this.header.replace(this.createMenuRowHeader(this.layer));
40
this.content.replace(this.createMenuRowContent(this.layer));
42
this.setupEventHandlers();
44
// Check to see if observation time matches the desired time
45
this.updateTimeStamp(this.layer);
49
* @method displayNewLayerOptions
51
displayNewLayerOptions: function () {
52
this.header = Builder.node('div', {className: 'layer-Head'}, "New Layer");
53
this.content = Builder.node('div');
54
this.domNode.appendChild(this.header);
55
this.domNode.appendChild(this.content);
59
var dn = self.layermanager.controller.dataNavigator;
61
// query list of available instruments if it is not already available
62
if (!dn.data.get('Instruments')) {
63
dn.query('Instruments');
67
// create select form-field for instrument choices
68
xhr = new Ajax.Updater(this.content, 'getInstruments.php', {
74
onComplete: function () {
75
var selectField = self.content.select('.instrument-select').first();
77
var onInstChange = function (e) {
78
//Debug.output(e.target.value + " chosen!");
79
// Get info for chosen instrument
80
var chosenInstrument = null;
81
for (var i = 0; i < dn.data.get('Instruments').length; i++) {
82
if (dn.data.get('Instruments')[i].instrument === e.target.value) {
83
chosenInstrument = dn.data.get('Instruments')[i];
86
self.layermanager.fire('newLayer', {menuEntry: self, instrument: chosenInstrument});
88
Event.observe(selectField, 'change', onInstChange.bind(self));
93
setupEventHandlers: function () {
94
// Function for toggling layer visibility
95
var toggleVisibility = function (e) {
96
var visible = this.layer.toggleVisible();
97
var icon = (visible ? 'LayerManagerButton_Visibility_Visible.png' : 'LayerManagerButton_Visibility_Hidden.png');
98
this.visibilityBtn.setStyle({ background: 'url(images/blackGlass/' + icon + ')' });
102
// Function for handling layer remove button
103
var removeLayer = function (e) {
104
this.layermanager.remove(this, this.layer);
105
Element.remove(this.domNode);
107
this.layermanager.render();
111
Event.observe(this.visibilityBtn, 'click', toggleVisibility.bindAsEventListener(this));
112
Event.observe(this.removeBtn, 'click', removeLayer.bindAsEventListener(this));
114
//NOTE 08-26-2008: Adding new event listener for updating timestamp
115
this.layer.addObserver('obs_time_change', this.onLayerChange.bind(this));
116
//this.layer.addObserver('change', this.onLayerChange.bind(this));
120
* @method createMenuRowHeader Creates the header for a header/content pair to be used
121
* within a jQuery accordion. The header describes the layer's associated instrument, the
122
* timestamp of the current image displayed, and icons for removing the layer and toggling
125
* @param {Layer} layer The tile layer
126
* @return {Dom-node} Returns a <div> element with all of the necessary components.
128
createMenuRowHeader: function (layer) {
129
var header = Builder.node('div', {className: 'layer-Head'});
130
var instrument = Builder.node('span', {id: 'layer-header-' + layer.id, style: 'float: left; width: 33%;'}, layer.instrument + (layer.instrument === layer.detector ? "" : "/" + layer.detector.trimLeft('0')) + " " + layer.measurement.trimLeft('0'));
132
//header.appendChild(instrument);
134
// Timestampdev/ie_floats/
135
var timestamp = Builder.node('span', {className: 'timestamp'});
138
this.visibilityBtn = Builder.node('button', {
139
id: 'visibility-button-' + layer.id,
140
className: 'layerManagerBtn visible',
143
title: ' - Toggle ' + layer.instrument + ' layer visibility.'
146
// Layer Removal Button
147
this.removeBtn = Builder.node('button', {
148
id: 'remove-button-' + layer.id,
149
className: 'layerManagerBtn remove',
152
title: ' - Remove layer.'
155
// Container for right-aligned elements
156
var rightSide = Builder.node('div', {style: 'text-align: right; float: left; width:67%;'}, [timestamp, " |", this.visibilityBtn, this.removeBtn]);
158
// combine left and right containers
159
var both = Builder.node('div', {style: 'overflow: hidden;' }, [instrument, rightSide]);
160
header.appendChild(both);
162
// header.appendChild(rightSide);
167
* @method createMenuRowContent
168
* @param {Layer} layer The tile layer.
169
* @return {Dom-node} The layer row content
171
createMenuRowContent: function (layer) {
173
var body = Builder.node('div', {style: 'color: white;'});
176
var instLeft = Builder.node('div', {style: 'float: left; width: 40%;'}, 'Instrument: ');
177
var instRight = Builder.node('div', {style: 'float: right; width: 60%;'}, this.createInstrumentControl(layer));
178
body.appendChild(Builder.node('div', {style: 'height: 24px; padding: 4px;', id: 'instrument-row-' + layer.id}, [instLeft, instRight]));
182
if (layer.measurements.length > 1) {
183
var left = Builder.node('div', {style: 'float: left; width: 40%;'}, 'Measurement: ');
184
//var right = Builder.node('div', {style: 'float: right; width: 60%;'}, this.createWavelengthControl(layer));
185
//body.appendChild(Builder.node('div', {style: 'height: 24px; padding: 4px;', id: 'measurement-row-' + layer.id}, [left, right]));
188
//get available measurements for chosen instrument
190
//var callBack = this.listMeasurements.bind(this);
191
//var xhr = new Ajax.Request('getMeasurements.php', {
192
// onSuccess: callBack,
194
// detector: layer.detector
197
/*this.measurementSelect = body.appendChild(Builder.node('div', {style: 'float: left; width: 100%;'}, " "));*/
200
//var opacityLeft = Builder.node('div', {style: 'float: left; width: 40%;'}, 'Opacity: ');
201
//var opacityRight = Builder.node('div', {style: 'float: right; width: 60%;'}, [this.createOpacityControl(layer.id), "%"]);
202
//body.appendChild(Builder.node('div', {style: 'height: 24px; padding: 4px;', id: 'opacity-row-' + layer.id}, [opacityLeft, opacityRight]));
207
listMeasurements: function (transport) {
208
var response = transport.responseJSON;
209
this.layer.measurementType = response[0].type;
211
this.layer.measurements = $A(response).collect(function (row) {
212
return parseInt(row.measurement, 10);
215
/*this.measurementSelect.update(this.layer.measurementType + ":");*/
220
* @method createInstrumentControl
222
createInstrumentControl: function (layer) {
223
var inst = new Element('select', {id: 'instrument-select-' + layer.id, style: 'display: none'});
226
//Available Instruments
227
//ToDo: Read availables from maps table, joined on instruments table for names
228
var instruments = $A(["EIT", "LASCO"]);
230
// Populate list of available instruments
231
for (var i = 0; i < instruments.length; i++) {
232
var opt = new Option(instruments[i]);
233
opt.value = instruments[i];
234
inst.options[inst.options.length] = opt;
237
// Set-up event handler to deal with an instrument change
238
Event.observe(inst, 'change', this.onInstrumentChange.curry(layer.id));
240
// Show only text until user clicks on the form item
241
//var instText = Builder.node('span', {id: 'instrument-text-' + layer.id}, inst.value);
242
var instText = Builder.node('span', {id: 'instrument-text-' + layer.id}, layer.instrument);
245
Event.observe(instText, 'click', function (e) {
250
Event.observe(inst, 'blur', function (e) {
255
//return [inst, instText];
260
* @method onInstrumentChange
263
onInstrumentChange: function (id) {
264
//Dom-nodes for layer components
265
var header = $('layer-header-' + id);
266
var measurement = $('wavelength-select-' + id);
267
var measurementRow = $('measurement-row-' + id);
268
var instText = $('instrument-text-' + id);
270
//Non-pretty solution... TODO: Create a function to handle parameter changes..
271
if (this.value === "LASCO") {
272
measurementRow.hide();
273
header.update("LASCO");
276
header.update(this.value + " " + measurement.value);
277
measurementRow.show();
280
//Update text to be displayed while not active
281
instText.update(this.value);
283
document.instrumentChange.fire(id, this.value);
286
onLayerChange: function (layer) {
287
// ToDo: update the other fields
288
this.updateTimeStamp(layer);
292
* @method createWavelengthControl
293
* @param {Int} The layer's id.
294
* @return {[Dom-node, Dom-node]} Returns a set of two dom-nodes to be inserted into the layer manager.
296
createWavelengthControl: function (layer) {
298
var wl = new Element('select', {id: 'wavelength-select-' + id, style: 'display: none'});
301
//Available wavelength choices for EIT
302
var wavelengths = $A([171, 195, 284]);
304
// Populate list of available wavelengths
305
for (var i = 0; i < wavelengths.length; i++) {
306
var opt = new Option(wavelengths[i]);
307
opt.value = wavelengths[i];
308
wl.options[wl.options.length] = opt;
311
// Set-up event handler to deal with an wavelength change
312
Event.observe(wl, 'change', this.onWavelengthChange.curry(id));
314
// Show only text until user clicks on the form item
315
//var wlText = Builder.node('span', {id: 'wavelength-text-' + id}, wl.value);
316
var wlText = Builder.node('span', {id: 'wavelength-text-' + id}, layer.measurement);
317
Event.observe(wlText, 'click', function (e) {
322
// Revert to text display after form field loses focus
323
Event.observe(wl, 'blur', function (e) {
332
* Event handler: wavelength change
334
onWavelengthChange: function (id) {
336
var inst = $('instrument-select-' + id);
337
var header = $('layer-header-' + id);
338
header.update(inst.value + " " + this.value);
340
//Update text to be displayed while not active
341
$('wavelength-text-' + id).update(this.value);
343
document.wavelengthChange.fire(id, this.value);
347
* @method createOpacityControl Creates the opacity control cell.
348
* @param {layer} The layer provider associated with the opacity control.
349
* @return {HTML Element} The opacity control cell.
351
createOpacityControl: function (id) {
353
var opacityInput = new Element('input', {size: '3', value: opacity});
355
Event.observe(opacityInput, 'change', function () {
356
document.opacityChange.fire(id, parseInt(this.value, 10) / 100);
363
* @method createEnabledBox Creates the enabled/disabled cell.
364
* @return {HTML Element} The enabled/disabled cell.
365
* @param {Integer} The layer's id
367
createEnabledBox: function (id) {
368
var enabledTd = new Element('td', {style: "padding-left:15px;"});
369
var enabled = new Element('input', {type: 'checkbox', checked: 'true', name: 'enabled'});
370
enabledTd.appendChild(enabled);
372
Event.observe(enabled, 'click', this.onEnabledBoxClick.bind(this, id));
377
* @method updateTimeStamp
381
updateTimeStamp: function () {
382
//var id = this.layer.id;
383
if (this.layer.timestamp === undefined) {
387
//remove any pre-existing styling
388
$(this.domNode).select(".timestamp").first().removeClassName("timeBehind");
389
$(this.domNode).select(".timestamp").first().removeClassName("timeAhead");
390
$(this.domNode).select(".timestamp").first().removeClassName("timeSignificantlyOff");
392
// Update the timestamp
393
var date = new Date(this.layer.timestamp * 1000);
394
var dateString = date.toYmdUTCString() + ' ' + date.toHmUTCString();
396
// Calc the time difference
397
var timeDiff = this.layer.timestamp - this.layermanager.controller.date.getTime() / 1000;
398
//var timeDiffAbs = Math.abs(timeDiff);
399
//var tdHours = Math.floor(timeDiffAbs / 3600);
400
//var tdMins = Math.floor((timeDiffAbs - tdHours * 3600) / 60);
401
//var tdSecs = (timeDiffAbs - tdHours * 3600) - tdMins * 60;
402
//var sign = (timeDiff === 0 ? '±' : (timeDiff > 0 ? '+' : '−'));
403
//var timeDiffStr = sign + String(tdHours) + ':' + String(tdMins).padLeft(0, 2) + ':' + String(tdSecs).padLeft(0, 2);
405
//this.domNode.select(".timestamp").first().update(dateString + ' ' + timeDiffStr);
406
$(this.domNode).select(".timestamp").first().update(dateString);
408
//get timestep (TODO: create a better accessor)
409
var ts = this.layermanager.controller.timeStepSlider.timestep.numSecs;
411
// Check to see if observation times match the actual time
413
if (Math.abs(timeDiff) > (4 * ts)) {
414
$(this.domNode).select(".timestamp").first().addClassName("timeSignificantlyOff");
417
$(this.domNode).select(".timestamp").first().addClassName("timeBehind");
420
else if (timeDiff > 0) {
421
if (timeDiff > (4 * ts)) {
422
$(this.domNode).select(".timestamp").first().addClassName("timeSignificantlyOff");
425
$(this.domNode).select(".timestamp").first().addClassName("timeAhead");
b'\\ No newline at end of file'