IONIC.defns ("api.imagearchive"); /** * @constructor * * @class * A {@link IONIC.api.imagearchive.ServerRef} points to an image * archive server. * *

* An image archive server can be in application scope, reachable * through an URL, ... *

*

* This is an abstract type. *

*/ IONIC.api.imagearchive.ServerRef = function () { }; /** * Get a server-friendly representation of the image archive server * reference, ready to be JSON-serialized. * *

* This dummy implementation will throw an exception *

* * @return {object} an object, ready to be JSON-serialized to the * server. */ IONIC.api.imagearchive.ServerRef.prototype.toTransportFormat = function () { IONIC.misc.unimp ("IONIC.api.imagearchive.ServerRef", "toTransportFormat"); }; /** * @constructor * * @class * An {@link IONIC.api.imagearchive.ApplicationScopeServerRef} points * to an image archive server that's available in the application * scope. * * @extends IONIC.api.imagearchive.ServerRef * */ IONIC.api.imagearchive.ApplicationScopeServerRef = function (id) { this._id = id; }; IONIC.misc.extendType (IONIC.api.imagearchive.ApplicationScopeServerRef, IONIC.api.imagearchive.ServerRef); /** * Get the ID in application scope under which this image archive * server is available. * * @return {string} the ID in application scope */ IONIC.api.imagearchive.ApplicationScopeServerRef.prototype.getId = function () { return this._id; }; /** * Get a server-friendly representation of the image archive server * reference * * @return {object} an object, ready to be JSON-serialized to the * server. */ IONIC.api.imagearchive.ApplicationScopeServerRef.prototype.toTransportFormat = function () { var tf = {}; tf.type = "applicationScope"; tf.id = this.getId (); return tf; }; /** * @constructor * * @class * An {@link IONIC.api.imagearchive.SessionScopeServerRef} points * to an image archive server that's available in the session * scope. * * @extends IONIC.api.imagearchive.ServerRef * */ IONIC.api.imagearchive.SessionScopeServerRef = function (id) { this._id = id; }; IONIC.misc.extendType (IONIC.api.imagearchive.SessionScopeServerRef, IONIC.api.imagearchive.ServerRef); /** * Get the ID in session scope under which this image archive * server is available. * * @return {string} the ID in session scope */ IONIC.api.imagearchive.SessionScopeServerRef.prototype.getId = function () { return this._id; }; /** * Get a server-friendly representation of the image archive server * reference * * @return {object} an object, ready to be JSON-serialized to the * server. */ IONIC.api.imagearchive.SessionScopeServerRef.prototype.toTransportFormat = function () { var tf = {}; tf.type = "sessionScope"; tf.id = this.getId (); return tf; }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. * * * IMPORTANT * * This file is internal to RedSpider Enterprise Tilapia toolkit * add-ons. It is subject to changes and CANNOT BE DIRECTLY ACCESSED * BY APPLICATIONS. Only the objects contained in the IONIC.api * package may be used. */ IONIC.defns ("imagearchive"); /** * @constructor * * @class * The {@link IONIC.imagearchive.ImageArchiveTool} is the low-level * JavaScript interface to an ImageArchive server. * * @extends IONIC.misc.RequestTool * *

* This shouldn't be used directly by applications, but is used by * higher-level tools. *

* * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the ImageArchive server */ IONIC.imagearchive.ImageArchiveTool = function (serverRef) { IONIC.misc.RequestTool.call (this); this._sr = serverRef; this.onQueryStart = new YAHOO.util.CustomEvent ("onQueryStart"); this.onQuery = new YAHOO.util.CustomEvent ("onQuery"); }; IONIC.misc.extendType (IONIC.imagearchive.ImageArchiveTool, IONIC.misc.RequestTool); /** * Get the ImageArchive server reference. * * @return {IONIC.api.imagearchive.ServerRef} the server reference */ IONIC.imagearchive.ImageArchiveTool.prototype.getServerRef = function () { return this._sr; }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getUrlForAction = function (action) { return IONIC.misc.getWebappBaseUrl () + "/" + action + ".do?serverRef=" + escape (JSON.stringify (this.getServerRef ().toTransportFormat ())); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getGetStatusUrl = function () { return this.getUrlForAction ("iaGetStatus"); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getSearchUrl = function (epsgId) { return this.getUrlForAction ("iaSearch") + "&epsgId=" + escape (epsgId); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getWfsSearchUrl = function (epsgId) { return this.getUrlForAction ("iaWfsSearch") + "&epsgId=" + escape (epsgId); }; /** * An URL that returns the ISO 19115 metadata corresponding to a feature type described * by its object id. * @param {string} id The object id. */ IONIC.imagearchive.ImageArchiveTool.prototype.getWfsISO19115SearchUrl = function (id) { return this.getUrlForAction ("iaWfsSearch") + "&action=iso19115&id=" + escape (id); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getGetObjectByNameUrl = function (name, epsgId, full) { return this.getUrlForAction ("iaGetByName") + "&objectName=" + escape (name) + "&epsgId=" + escape (epsgId) + "&fullDescription=" + escape (full); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getGetObjectByIdUrl = function (id, epsgId, full) { return this.getUrlForAction ("iaGetByName") + "&objectId=" + escape (id) + "&epsgId=" + escape (epsgId) + "&fullDescription=" + escape (full); }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.prototype.getGetCoverageByNameUrl = function (name, epsgId, full) { return this.getUrlForAction ("iaCoverageByName") + "&objectName=" + escape (name) + "&epsgId=" + escape (epsgId) + "&fullDescription=" + escape (full); }; /** * The default width of a thumbnail */ IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_WIDTH = +("100" || 100); /** * The default height of a thumbnail */ IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_HEIGHT = +("100" || 100); /** * Build the URL for fetching, as an image, the thumbnail * corresponding to the object with the given name. * * @param {string} objectName The name of the object * @param {int} width (optional) The width, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_WIDTH}. * @param {int} height (optional) The height, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_HEIGHT}. */ IONIC.imagearchive.ImageArchiveTool.prototype.getThumbnailUrl = function (objectName, width, height) { var base = this.getUrlForAction ("iaThumbnail"); return base + "&objectName=" + escape(objectName) + "&width=" + (width || IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_WIDTH) + "&height=" + (height || IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_HEIGHT); }; /** * @constructor * * @class * This defines a custom queryable for the search panel. * *

* A custom queryable is a search criteria that the server * advertises as being available, and is one of the types: *

*

* * @param {string} name The name of the search criteria * @param {string} title The title, which will be displayed * @param {string} type The type, one of the enum entry above. * // @ param def The default value */ IONIC.imagearchive.ImageArchiveTool.Queryable = function (name, title, type/*, def*/) { this._n = name; this._t = title; this._tp = type; //this._def = def; }; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_EQL = "equal"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_GREATER_OR_EQL = "greaterOrEqual"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_GREATER = "greater"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LESS_OR_EQL = "lessOrEqual"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LESS = "less"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LIKE = "like"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.OP_DATE_BETWEEN = "dateBetween"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_DATE = "date"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_INT = "int"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_STRING = "string"; /** * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_ENUM = "enum"; /** * Retrieve the name of this queryable. * * @return {string} */ IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.getName = function () { return this._n; }; /** * Retrieve the title of this queryable. * * @return {string} */ IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.getTitle = function () { return this._t; }; /** * Retrieve the type of this queryable. * * @return {string} the type */ IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.getType = function () { return this._tp; }; /** * Retrieve the enumeration values, if any * * @return {string[]} the enumeration values, or undefined */ IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.getEnumValues = function () { return this._ev; }; /** * Set the enumeration values * * @param {string[]} evs The enumeration values * @private */ IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.setEnumValues = function (evs) { this._ev = evs; }; // /** // * Retrieve the default value of this queryable. // * // * @return the default value // */ // IONIC.imagearchive.ImageArchiveTool.Queryable.prototype.getDefaultValue = function () { // return this._def; // }; /** * Retrieve the status from the server * FIXME: What's the format of the status object? --ad 070814 * * @param {function} callback A function of one argument: The status object */ IONIC.imagearchive.ImageArchiveTool.prototype.withServerStatus = function (callback) { var url = this.getGetStatusUrl (); this.withUrl ( url, "GET", function (success, statusObj) { if (callback) { // Make the custom queryables // real typed objects statusObj.customQueryables = IONIC.misc.mapcar1 (function (cco) { var q = new IONIC.imagearchive.ImageArchiveTool.Queryable ( cco.name, cco.title, cco.type); // Has enumeration if (cco.enumeration) { q.setEnumValues (cco.enumeration); } return q; }, statusObj.customQueryables); callback (statusObj); } }); }; /** * Execute a search on the ImageArchive server, according to the * parameters that are passed as arguments. * * @param {string} keywords A string of keywords (separated by white * spaces) * * @param {string} resultType The type of results we expect (granule, aggregate) * * @param {string} resultAvailability The availability of results we * expect (WMS, WCS, both, ...) * * @param {int} resultsCount The max number of results (-1 means: no * limit) * * @param {object} spatialBounds A geometry, from the package * IONIC.api.geom.*, or null/undefined if no spatial boundary * * @param {string[]} temporalBounds An array of two ISO8601-formatted * dates. If the array is null/undefined, there is no temporal * boundary. Also, if either of the two (or the two) boundaries are * null/undefined, those will be ignored * * @param {int} minimumQuality A percentage indicating the minimum * quality of the results we expect (from 0 to 100). (-1 means: no * specific minimum quality required) * * @param {int} minimumResolution The minimum resolution FIXME: what * does that mean?? --ad 070814 * * @param {object[]} customQueryables An array of objects holding * the properties name, operator and * value, for searching on custom parameters. * * @param {int} epsgId The EPSG ID in which the spatial extent must be * expressed * * @param {function} beginCallback The begin callback * * @param {function} iterationCallback The iteration callback * * @param {function} endCallback The end callback */ IONIC.imagearchive.ImageArchiveTool.prototype.executeSearch = function (keywords, resultsType, resultsAvailability, resultsCount, spatialBounds, temporalBounds, minimumQuality, minimumResolution, customQueryables, epsgId, beginCallback, iterationCallback, endCallback) { var self = this; var query = { keywords : keywords, resultsType : resultsType, resultsAvailability : resultsAvailability, resultsCount : resultsCount, spatialBounds : spatialBounds ? IONIC.geom.JGTFTool.geometryToJGTF (spatialBounds) : undefined, temporalBounds : temporalBounds ? ( IONIC.misc.mapcar1 ( function (date) { if (date) { return date.toISO8601String (); } else { return null; } }, temporalBounds)) : undefined, minimumQuality : minimumQuality, minimumResolution : minimumResolution, customQueryables : customQueryables }; var serverRef = this.getServerRef (); var queryId = gensym (); var time = new Date ().getTime (); this.onQueryStart.fire ("search", query, queryId); this.withUrl (this.getSearchUrl (epsgId), "POST", this._wrapIterationCallbacks ( beginCallback, iterationCallback, function (success, parsedObject, thisReq) { self.onQuery.fire ("search", query, parsedObject, (new Date ().getTime () - time) / 1000, queryId); if (endCallback) { endCallback.apply (self, arguments); } }, null, null, function (data) { return IONIC.api.imagearchive.IAObject.fromTransportFormat( serverRef, data); }, "records"), JSON.stringify (query)); }; /** * Execute a search for WFS objects on the ImageArchive server, according to the * parameters that are passed as arguments. * * @param {string} keywords A string of keywords (separated by white * spaces) * * @param {int} resultsCount The max number of results (-1 means: no * limit) * * @param {object} spatialBounds A geometry, from the package * IONIC.api.geom.*, or null/undefined if no spatial boundary * * @param {string[]} temporalBounds An array of two ISO8601-formatted * dates. If the array is null/undefined, there is no temporal * boundary. Also, if either of the two (or the two) boundaries are * null/undefined, those will be ignored * * @param {int} epsgId The EPSG ID in which the spatial extent must be * expressed * * @param {function} beginCallback The begin callback * * @param {function} iterationCallback The iteration callback * * @param {function} endCallback The end callback */ IONIC.imagearchive.ImageArchiveTool.prototype.executeWfsSearch = function (keywords, resultsCount, spatialBounds, temporalBounds, epsgId, beginCallback, iterationCallback, endCallback) { var self = this; var query = { keywords : keywords, resultsCount : resultsCount, spatialBounds : spatialBounds ? IONIC.geom.JGTFTool.geometryToJGTF (spatialBounds) : undefined, temporalBounds : temporalBounds ? ( IONIC.misc.mapcar1 ( function (date) { if (date) { return date.toISO8601String (); } else { return null; } }, temporalBounds)) : undefined }; var serverRef = this.getServerRef (); var time = new Date ().getTime (); var queryId = gensym (); this.onQueryStart.fire ("wfsSearch", query, queryId); this.withUrl (this.getWfsSearchUrl (epsgId), "POST", this._wrapIterationCallbacks ( beginCallback, iterationCallback, function (success, parsedObject, thisReq) { self.onQuery.fire ("wfsSearch", query, parsedObject, (new Date ().getTime () - time) / 1000, queryId); if (endCallback) { endCallback.apply (self, arguments); } }, null, null, function (wfsObject) { if (wfsObject.footprint) { wfsObject.footprint = IONIC.geom.JGTFTool.JGTFToGeometry (wfsObject.footprint); } return wfsObject; }, "wfsRecords"), JSON.stringify (query)); }; /** * Fetch the object corresponding to the given name. * *

* By default, only the primary information about that object is * retrieved. If you want to retrieve (parts of) information about * the children of this object, as well as the axes/bands this * coverage object might propose, you'll need to pass * true as last parameter. *

* * @param {string} name The name of the object * * @param {int} epsgId The EPSG ID in which the spatial extent must be * expressed * * @param {function} callback A function of one argument * (a {@link IONIC.api.imagearchive.IAObject}) * * @param {boolean} full (optional) Pass true if you want * to retrieve information about the children and the axes/bands. * * @see #withCoverageByName */ IONIC.imagearchive.ImageArchiveTool.prototype.withObjectByName = function (name, epsgId, callback, full) { // the name is actually a uuid; call proper method if (name.indexOf("urn:")>=0) return this.withObjectById(name, epsgId, callback, full); if (typeof epsgId !== "number") throw "Missing EPSG ID"; var self = this; var time = new Date ().getTime (); var queryId = gensym (); this.onQueryStart.fire ("objectByName", name, queryId); this.withUrl (this.getGetObjectByNameUrl (name, epsgId, !! full), "GET", function (success, data) { self.onQuery.fire ("objectByName", name, data, (new Date ().getTime () - time) / 1000, queryId); if (callback) { var obj = IONIC.api.imagearchive.IAObject.fromTransportFormat( self.getServerRef (), data); obj.isFull = full; callback(obj); } }); }; /** * Fetch the object corresponding to the given uuid. * *

* By default, only the primary information about that object is * retrieved. If you want to retrieve (parts of) information about * the children of this object, as well as the axes/bands this * coverage object might propose, you'll need to pass * true as last parameter. *

* * @param {string} id The id of the object * * @param {int} epsgId The EPSG ID in which the spatial extent must be * expressed * * @param {function} callback A function of one argument * (a {@link IONIC.api.imagearchive.IAObject}) * * @param {boolean} full (optional) Pass true if you want * to retrieve information about the children and the axes/bands. * * @see #withCoverageByName */ IONIC.imagearchive.ImageArchiveTool.prototype.withObjectById = function (id, epsgId, callback, full) { if (typeof epsgId !== "number") throw "Missing EPSG ID"; var self = this; var time = new Date ().getTime (); var queryId = gensym (); this.onQueryStart.fire ("objectByName", id, queryId); this.withUrl (this.getGetObjectByIdUrl (id, epsgId, !! full), "GET", function (success, data) { self.onQuery.fire ("objectByName", id, data, (new Date ().getTime () - time) / 1000, queryId); if (callback) { var obj = IONIC.api.imagearchive.IAObject.fromTransportFormat( self.getServerRef (), data); obj.isFull = full; callback(obj); } }); }; /** * Fetch the object corresponding to the given name, * as a coverage (which means this will include more information, such * as: the axes, request/response CRSes, formats, ...). * *

* By default, only the primary information about that object is * retrieved. If you want to retrieve (parts of) information about * the children of this object, as well as the axes/bands this * coverage object might propose, you'll need to pass * true as last parameter. *

* * @param {string} name The name of the object * * @param {int} epsgId The EPSG ID in which the spatial extent must be * expressed * * @param {function} callback A function of one argument * (a {@link IONIC.api.imagearchive.IAObject}) * * @param {boolean} full (optional) Pass true if you want * to retrieve information about the children and the axes/bands. * * @see #withObjectByName */ IONIC.imagearchive.ImageArchiveTool.prototype.withCoverageByName = function (name, epsgId, callback, full) { // FIXME: lots of copy/paste code w/ prev fun. --ad 070903 if (typeof epsgId !== "number") throw "Missing Epsg Id"; var self = this; var time = new Date ().getTime (); var queryId = gensym (); this.onQueryStart.fire ("coverageByName", name, queryId); this.withUrl (this.getGetCoverageByNameUrl (name, epsgId, !! full), "GET", function (success, data) { self.onQuery.fire ("objectByName", name, data, (new Date ().getTime () - time) / 1000, queryId); if (callback) { callback (IONIC.api.imagearchive.IAObject.fromTransportFormat( self.getServerRef (), data)); } }); }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. * * * IMPORTANT * * This file is internal to RedSpider Enterprise Tilapia toolkit * add-ons. It is subject to changes and CANNOT BE DIRECTLY ACCESSED * BY APPLICATIONS. Only the objects contained in the IONIC.api * package may be used. */ /** * Build an abstract panel * @constructor * * @extends IONIC.imagearchive.AbstractImageArchivePanel * * @class * * A {@link IONIC.imagearchive.AbstractImageArchivePanel} is the base * for all ImageArchive panels * * @param {HTMLElement} htmlElt The containing HTML element, or it's * ID. * * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the image archive server * * @param {HTMLWindow} win (Optional) The window in which is the * document holding the element named "htmlElt", if "htmlElt" is * a string (defaults to the current window). */ IONIC.imagearchive.AbstractImageArchivePanel = function (htmlElt, serverRef, win) { win = win || window; var dh = new IONIC.api.ui.DomHelper (win.document); this._dh = dh; this._iastool = new IONIC.imagearchive.ImageArchiveTool (serverRef); this._editors = {}; this._htmlElt = dh.get(htmlElt); }; /** * Get the associated {@link IONIC.imagearchive.ImageArchiveTool} * * @return {IONIC.imagearchive.ImageArchiveTool} */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getImageArchiveTool = function () { return this._iastool; }; /** * Get the {@link IONIC.api.ui.DomHelper} associated to this panel. * * @return {IONIC.api.ui.DomHelper} the helper */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getDomHelper = function () { return this._dh; }; /** * Get the HTMLElement associated with this panel. * * @return {HTMLElement} the element */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getElement = function () { return this._htmlElt; }; /** * Get the {@link IONIC.api.imagearchive.ServerRef} associated to this * panel. * * @return {IONIC.api.imagearchive.ServerRef} the server reference */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getServerRef = function () { return this.getImageArchiveTool ().getServerRef (); }; /** * Get the {@link IONIC.api.maps.Map} that is associated to this * instance. * * @return {IONIC.api.maps.Map} the associated map */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getAssociatedMap = function () { return this._map; }; /** * Set the {@link IONIC.api.maps.Map} that is associated to this * instance. * *

* Attaching a {@link IONIC.api.maps.Map} to an instance of this * type will force the ImageArchive objects' spatial extents to be * expressed in that map's EPSG ID. *

* * @param {IONIC.api.maps.Map} map The map to be associated to this * instance. */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.setAssociatedMap = function (map) { this._map = map; }; /** * Returns the preferred epsg ID for any query this panel might have * to make. * *

* If there is a {@link IONIC.api.maps.Map} associated to this * panel, it's epsgId will be used. Otherwise, -1 is returned. *

* * @return {int} the epsg ID */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getPreferredEpsgId = function () { var map = this.getAssociatedMap (); return ((map && map.getBox ()) ? map.getBox ().epsgId : -1); }; /** * Builds an {@link IONIC.ui.AbstractSpatialEditor} that will be used * for retrieving the box for a query. * *

* This implementation will simply build an editable <input> * field-based editor that, when asked for it's value * (see {@link IONIC.ui.AbstractEditor#getValue}) will try and * read a comma-separated representation of a box in what's been * typed in and return a geometry (a {@link IONIC.api.geom.Polygon}) * if it succeeds. *

*

* It's up to the implementation/specialization of this * {@link IONIC.imagearchive.AbstractImageArchivePanel} to fill the * editor with the comma-separated representation of a box. (for * example, by listening to the "onSelectedBoxChanged" event of a * {@link IONIC.api.maps.Map}). *

*

* Note: When the getValue function is called on * an editor that is created by this function, the returned type * will be a {@link IONIC.api.geom.Polygon} of 1 ring, with 4 * points, representing the box, and not a * {@link IONIC.api.geom.Box} instance. *

* * @param {IONIC.api.ui.DomHelper} dh A dom helper * * @param {IONIC.imagearchive.AbstractImageArchivePanel} panelInstance * An instance of the panel in which the editor will be inserted * * @return {IONIC.ui.InputEditor} a new {@link IONIC.ui.InputEditor} * instance */ IONIC.imagearchive.AbstractImageArchivePanel.buildBoundingBoxEditor = function (dh, panelInstance) { var editor = IONIC.ui.InputEditor.newInstance (dh); IONIC.misc.createCustomEvents (["onValueManuallyChanged"], editor); var ptStr = function (pt) { return pt.toStringExt (",", true); }; editor.setValue = function (geometryOrBox) { this.geometricValue = geometryOrBox; var txt = editor.geometryOrBoxToText (geometryOrBox); IONIC.ui.InputEditor.prototype.setValue.call (this, txt); }; editor.getValue = function () { var value = this.geometricValue; if (! value) { return; } if (value instanceof IONIC.api.geom.Box) { // box -> polygon return value.toPolygon (); } else { // geometry return value; } }; editor.getComponent ().onchange = function () { var typedValue = editor.getComponent ().value; var geom, geditLayer; if (typedValue === "" || (typeof typedValue === "undefined")) { editor.setValue (null); editor.onValueManuallyChanged.fire (null); } else { geom = editor.textToGeometryOrBox (typedValue); editor.setValue (geom); editor.onValueManuallyChanged.fire (geom); } }; editor.geometryOrBoxToText = function (geom) { var txt = ""; var types, tl, br, i, parts, ring; if (geom instanceof IONIC.api.geom.Box) { txt = ptStr (geom.getTopLeft ()) + " " + ptStr (geom.getBottomRight ()); } else { types = IONIC.geom.GeometryTypes; if (geom) { switch (types.get (geom)) { case types.TYPE_POINT: txt = ptStr (geom); break; case types.TYPE_LINE_STRING: parts = []; for (i = 0, n = geom.countVertices (); i < n; i ++) { parts.push (ptStr (geom.getPointAt ([i]))); } txt = parts.join (" "); break; case types.TYPE_POLYGON: parts = []; // Keep 1st ring only geom = geom.getChild (0); for (i = 0, n = geom.countVertices (); i < n; i ++) { parts.push (ptStr (geom.getPointAt ([i]))); } txt = parts.join (" "); break; } } } return txt; }; editor.textToGeometryOrBox = function (text) { var geom, data, data2; var map = panelInstance.getAssociatedMap (); var epsgId = (map ? map.getBox ().epsgId : 4326); var parts = IONIC.misc.subset (function (part) { return part !== ""; }, (text || "").split (" ")); var parsePt = function (ptTxt) { var ptParts = ptTxt.split (","); var x, y; if (ptParts.length !== 2) { return; } else { x = + (ptParts [0]); y = + (ptParts [1]); if (typeof x !== "number" || isNaN (x) || typeof y !== "number" || isNaN (y)) { return; } return [x, y]; } }; switch (parts.length) { case 0: break; case 1: // Try and build a point data = parsePt (parts [0]); if (data) { geom = new IONIC.api.geom.Point (data [0], data [1], epsgId); } break; case 2: // Try and build a box data = parsePt (parts [0]); data2 = parsePt (parts [1]); if (data && data2) { geom = new IONIC.api.geom.Box ( data [0], data [1], data2 [0], data2 [1], epsgId); } break; default: // Try and build a polygon ring = new IONIC.api.geom.LinearRing (null, epsgId); IONIC.misc.forEach ( function (part) { if (ring) { data = parsePt (part); if (data) { ring.pushPoints (new IONIC.api.geom.Point ( data [0], data [1], epsgId)); } else { // Invalidate // the thing ring = null; } } }, parts); if (ring) { geom = new IONIC.api.geom.Polygon (epsgId); geom.pushChild (ring); } break; } return geom; }; return editor; }; /** * Register the editor under the specified name. * * @param {string} name The name of the editor * @param {IONIC.ui.AbstractEditor} editor The editor */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.registerEditor = function (name, editor) { this._editors [name] = editor; }; /** * Get editor registered under the specified name. * * @param {string} name The name of the editor * @return {IONIC.ui.AbstractEditor} the editor */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.getEditor = function (name) { return this._editors [name]; }; /** * For each editor, call a function. * * @param {function} fun A function of two arguments: the * {@link IONIC.ui.AbstractEditor}, and a string: the name * under which it was registered. */ IONIC.imagearchive.AbstractImageArchivePanel.prototype.forEachEditor = function (fun) { var eds = this._editors, id; for (id in eds) { if (eds.hasOwnProperty (id)) { fun (eds [id], id); } } }; /** * @constructor * * @class * This class allows to create and display a popup window that describes an object. When a * popup is created, it is first hidden and must be made visible using {@link #show}. * * @param {IONIC.api.ui.DomHelper} A DOM helper. */ IONIC.imagearchive.AbstractPopup = function(dh) { this.dh = dh; this.elt = null; this.delay = 0; this.isVisible = false; this.displayedObject = null; }; /** * Sets the object represented by this popup. * This method should be overridden to create the HTML corresponding to the object. * * @param {Object} object The object. */ IONIC.imagearchive.AbstractPopup.prototype.setContent = function(object) { // Skip if already set if (this.displayedObject == object) return; this.displayedObject = object; }; /** * The delay before making the popup appear. * * @param {int} delay The delay, in ms. */ IONIC.imagearchive.AbstractPopup.prototype.setDelay = function(delay) { this.delay = delay; }; /** * @ignore * @return {HTMLElement} the element. */ IONIC.imagearchive.AbstractPopup.createHTMLElement = function(dh) { var elt = dh.elt("div.rowResult"); var s = elt.style; s.display = "none"; dh.append(dh.getDocument ().body, elt); return elt; }; /** * Returns the HTML element representing the popup. * * @return {HTMLElement} the element. */ IONIC.imagearchive.AbstractPopup.prototype.getHTMLElement = function() { if (!this.elt) this.elt = IONIC.imagearchive.AbstractPopup.createHTMLElement(this.dh); return this.elt; }; /** * Shows the popup. The (optional) delay is applied. */ IONIC.imagearchive.AbstractPopup.prototype.show = function() { var self = this; this.isVisible = true; // If no iaObject has been set, nothing to show if (!this.displayedObject) return; if (this.delay > 0) setTimeout(showImmediately, this.delay); else showImmediately(); function showImmediately() { if (!self.isVisible) return; var elt = self.getHTMLElement(); elt.style.display = ""; } } /** * Hides the popup. */ IONIC.imagearchive.AbstractPopup.prototype.hide = function() { this.isVisible = false; if (this.elt) this.elt.style.display = "none"; }; /** * Destroys the popup. */ IONIC.imagearchive.AbstractPopup.prototype.destroy = function() { if (this.elt) this.dh.rmv(this.elt); }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. * * * IMPORTANT * * This file is internal to RedSpider Enterprise Tilapia toolkit * add-ons. It is subject to changes and CANNOT BE DIRECTLY ACCESSED * BY APPLICATIONS. Only the objects contained in the IONIC.api * package may be used. */ IONIC.defns ("imagearchive.editors"); /** * @constructor * * @class * An editor, based on an <input> element, that implements the * {@link #getOperator} function. * *

* In order to get the {@link #getOperator} to work properly, the * component for this editor must embed an HTML <select> * element, allowing the user to select the operator. *

* * @extend IONIC.ui.InputEditor * * @param {HTMLElement} component An HTML component */ IONIC.imagearchive.editors.CustomQueryableInputEditor = function (component) { IONIC.ui.InputEditor.call (this, component); }; IONIC.misc.extendType (IONIC.imagearchive.editors.CustomQueryableInputEditor, IONIC.ui.InputEditor); /** * Make a new instance * * @param {IONIC.api.ui.DomHelper} dh A dom helper to build the * element * @return {IONIC.ui.InputEditor} */ IONIC.imagearchive.editors.CustomQueryableInputEditor.newInstance = function (dh) { var div = IONIC.imagearchive.editors.CustomQueryableInputEditor.buildComponent (dh); return new IONIC.imagearchive.editors.CustomQueryableInputEditor (div); }; /** * Builds a component useful for the {@link IONIC.imagearchive.editors.CustomQueryableInputEditor} * editor. * * @param {IONIC.api.ui.DomHelper} dh A DOM helper used to build the component. * @param {boolean} includeLikeOperator Include the 'like' operator in the choice list. * @return {HTMLElement} The element built. */ IONIC.imagearchive.editors.CustomQueryableInputEditor.buildComponent = function (dh, includeLikeOperator) { if (typeof includeLikeOperator === "undefined") { includeLikeOperator = true; } var inp = dh.elt ("input"); inp.type = "text"; inp.disabled = true; var stor = dh.elt ("select"); dh.mkOpt (stor, "- Select -").value = "- Select -"; dh.mkOpt (stor, "=").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_EQL; dh.mkOpt (stor, ">=").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_GREATER_OR_EQL; dh.mkOpt (stor, ">").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_GREATER; dh.mkOpt (stor, "<=").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LESS_OR_EQL; dh.mkOpt (stor, "<").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LESS; if (includeLikeOperator) { dh.mkOpt (stor, "like").value = IONIC.imagearchive.ImageArchiveTool.Queryable.OP_LIKE; } // Disable values selector if operator is not selected stor.onchange = function () { inp.disabled = (stor.options.selectedIndex == 0) ? true : false; }; return dh.elt ("div", stor, inp); }; /** * Returns the operator that was selected (null if none). * * @return the operator */ IONIC.imagearchive.editors.CustomQueryableInputEditor.prototype.getOperator = function () { var stor = this.getComponent ().getElementsByTagName ("select") [0]; if (stor.options.selectedIndex == 0) { return null; } return stor.options [stor.options.selectedIndex].value; }; /** * Returns the value that was entered (null if none). * * @return the value */ IONIC.imagearchive.editors.CustomQueryableInputEditor.prototype.getValue = function () { if (!this.getOperator ()) { return null; } return this.refineValue (this.getComponent ().getElementsByTagName ("input") [0].value); }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. */ /** * @constructor * * @class * A date editor. * * @extend IONIC.ui.InputEditor * *

* Since building an HTML component for this type of editor is * rather complex, and follows strict rules, you might want to have * a look at * {@link IONIC.imagearchive.editors.CustomQueryableDateEditor#buildComponent}. *

* * @param {HTMLElement} component An HTML component for this editor * * @see IONIC.imagearchive.editors.CustomQueryableDateEditor#buildComponent */ IONIC.imagearchive.editors.CustomQueryableDateEditor = function (component) { IONIC.ui.InputEditor.call (this, component); }; IONIC.misc.extendType (IONIC.imagearchive.editors.CustomQueryableDateEditor, IONIC.ui.InputEditor); IONIC.imagearchive.editors.CustomQueryableDateEditor.newInstance = function (dh) { var component = IONIC.imagearchive.editors.CustomQueryableDateEditor.buildComponent (dh); return new IONIC.imagearchive.editors.CustomQueryableDateEditor (component); } /** * Retrieve the value for this editor. * * @return {Date} the selected date. */ IONIC.imagearchive.editors.CustomQueryableDateEditor.prototype.getValue = function () { return this.getComponent ().getValue (); }; /** * Retrieve the operator for this editor. * * @return {string} the operator. */ IONIC.imagearchive.editors.CustomQueryableDateEditor.prototype.getOperator = function () { return this.getComponent ().getOperator (); }; /** * Build an HTML component, typically targetted at the * {@link IONIC.imagearchive.editors.CustomQueryableDateEditor} * type. * *

* The component will have two properties, namely * "getOperator" and "getValue" from where an * {@link IONIC.imagearchive.editors.CustomQueryableDateEditor} * instance will be able to retrieve the information it needs. *

* * @param {IONIC.api.ui.DomHelper} dh A DomHelper to build the * component * @return {HTMLElement} an HTML component */ IONIC.imagearchive.editors.CustomQueryableDateEditor.buildComponent = function (dh) { var inputComponent = IONIC.imagearchive.editors.CustomQueryableInputEditor.buildComponent (dh, false); var inputEditor = new IONIC.imagearchive.editors.CustomQueryableInputEditor (inputComponent); var dateComponent = inputComponent.getElementsByTagName("input")[0]; var operatorComponent = inputComponent.getElementsByTagName("select")[0]; var startCalendarHolder = dh.elt ("div.timestampCalendar"); startCalendarHolder.id = gensym ("cphdr"); startCalendarHolder.style.position = "absolute"; startCalendarHolder.style.visibility = "hidden"; startCalendarHolder.style.backgroundColor = "white"; dh.append (dh.getDocument ().body, startCalendarHolder); var startCalendarHook = dh.elt ("img"); startCalendarHook.id = gensym ("chk"); startCalendarHook.src = IONIC.misc.getWebappBaseUrl () + "/images/editor/timestamp/calendar.gif"; startCalendarHook.alt = "calendar"; startCalendarHook.title = "Open calendar"; var startClear = dh.elt ("img"); startClear.src = IONIC.misc.getWebappBaseUrl () + "/images/editor/timestamp/clear.gif"; startClear.alt = "tilapia.editor.timestamp.clear.alt"; startClear.title = "tilapia.editor.timestamp.clear.title"; var startCal = new CalendarPopup (startCalendarHolder.id); var win = window; // DH should provide this! var startCBName = gensym ("startCalCb"); win [startCBName] = function (y, m, d) { var date = new Date (y, m, d); dateComponent.value = date.toLocaleDateString (); dateComponent.dateValue = date; }; startCal.setReturnFunction (startCBName); startCalendarHook.onclick = function () { startCal.showCalendar (startCalendarHook.id); return false; }; startClear.onclick = function () { dateComponent.value = ""; dateComponent.dateValue = undefined; }; var cpnt = dh.elt ("div", inputComponent, startCalendarHook, startClear); cpnt.getValue = function () { return dateComponent.dateValue; }; cpnt.getOperator = function () { return inputEditor.getOperator (); }; return cpnt; }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. */ /** * @constructor * * @class * A date editor. * * @extend IONIC.ui.InputEditor * *

* Since building an HTML component for this type of editor is * rather complex, and follows strict rules, you might want to have * a look at * {@link IONIC.imagearchive.editors.CustomQueryableIntEditor#buildComponent}. *

* * @param {HTMLElement} component An HTML component for this editor * * @see IONIC.imagearchive.editors.CustomQueryableIntEditor#buildComponent */ IONIC.imagearchive.editors.CustomQueryableIntEditor = function (component) { IONIC.ui.InputEditor.call (this, component); }; IONIC.misc.extendType (IONIC.imagearchive.editors.CustomQueryableIntEditor, IONIC.imagearchive.editors.CustomQueryableInputEditor); IONIC.imagearchive.editors.CustomQueryableIntEditor.newInstance = function (dh) { var component = IONIC.imagearchive.editors.CustomQueryableIntEditor.buildComponent (dh); return new IONIC.imagearchive.editors.CustomQueryableIntEditor (component); } /** * Retrieve the value for this editor. * * @return {int} the selected date. */ IONIC.imagearchive.editors.CustomQueryableIntEditor.prototype.getValue = function () { return this.getComponent ().getValue (); }; /** * Retrieve the operator for this editor. * * @return {string} the operator. */ IONIC.imagearchive.editors.CustomQueryableIntEditor.prototype.getOperator = function () { return this.getComponent ().getOperator (); }; /** * Build an HTML component, typically targetted at the * {@link IONIC.imagearchive.editors.CustomQueryableIntEditor} * type. * *

* The component will have two properties, namely * "getOperator" and "getValue" from where an * {@link IONIC.imagearchive.editors.CustomQueryableIntEditor} * instance will be able to retrieve the information it needs. *

* * @param {IONIC.api.ui.DomHelper} dh A DomHelper to build the * component * @return {HTMLElement} an HTML component */ IONIC.imagearchive.editors.CustomQueryableIntEditor.buildComponent = function (dh) { var inputComponent = IONIC.imagearchive.editors.CustomQueryableInputEditor.buildComponent (dh, false); var inputEditor = new IONIC.imagearchive.editors.CustomQueryableInputEditor (inputComponent); inputComponent.getValue = function () { return parseInt (inputEditor.getValue ()); }; inputComponent.getOperator = function () { return inputEditor.getOperator (); }; return inputComponent; }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. * * * IMPORTANT * * This file is internal to RedSpider Enterprise Tilapia toolkit * add-ons. It is subject to changes and CANNOT BE DIRECTLY ACCESSED * BY APPLICATIONS. Only the objects contained in the IONIC.api * package may be used. */ IONIC.defns ("imagearchive.editors"); /** * @constructor * * @class * An editor, based on an <select> element, that implements the * {@link #getOperator} function * * @extend IONIC.ui.SelectEditor * * @param {HTMLSelect} component An HTML <select> element. */ IONIC.imagearchive.editors.CustomQueryableSelectEditor = function (component) { IONIC.ui.InputEditor.call (this, component); }; IONIC.misc.extendType (IONIC.imagearchive.editors.CustomQueryableSelectEditor, IONIC.ui.InputEditor); IONIC.imagearchive.editors.CustomQueryableSelectEditor.newInstance = function (dh) { var opSelect = new IONIC.ui.SelectEditor (dh.elt ("select")); opSelect.setOptions ([ "=" ], dh); valuesSelect = new IONIC.ui.SelectEditor (dh.elt ("select")); valuesSelect.getComponent ().disabled = true; // initially disabled var div = dh.elt ("div", opSelect.getComponent (), valuesSelect.getComponent ()); // Disable values selector if operator is not selected opSelect.getComponent ().onchange = function () { valuesSelect.getComponent ().disabled = (opSelect.getValue ()) ? false : true; }; var instance = new IONIC.imagearchive.editors.CustomQueryableSelectEditor (div); instance.opSelect = opSelect; instance.valuesSelect = valuesSelect; return instance; }; IONIC.imagearchive.editors.CustomQueryableSelectEditor.prototype.setOptions = function (ev, dh, noprompt) { this.valuesSelect.setOptions (ev, dh, noprompt); }; /** * Returns * {@link IONIC.imagearchive.ImageArchiveTool.Queryable.OP_EQL}. * * @return {IONIC.imagearchive.ImageArchiveTool.Queryable.OP_EQL} */ IONIC.imagearchive.editors.CustomQueryableSelectEditor.prototype.getOperator = function () { return IONIC.imagearchive.ImageArchiveTool.Queryable.OP_EQL; }; /** * Returns the value of this select box, or undefined if unknown. * * @return {string} the value. */ IONIC.imagearchive.editors.CustomQueryableSelectEditor.prototype.getValue = function () { if (this.opSelect.getValue ()) { return this.valuesSelect.getValue (); } else { return undefined; } }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. * * * IMPORTANT * * This file is internal to RedSpider Enterprise Tilapia toolkit * add-ons. It is subject to changes and CANNOT BE DIRECTLY ACCESSED * BY APPLICATIONS. Only the objects contained in the IONIC.api * package may be used. */ IONIC.defns ("imagearchive.editors"); /** * Build a channel-selector editor * * @constructor * * @extends IONIC.ui.AbstractMultiValuedEditor * * @class * An editor, based on an <select> element, with multiple * choices allowed, that allow the user to select what channels/bands * to retrieve in a GetCoverage request. * *

* This type of editor requires a very specific type of * component. Unless you absolutely know what you're doing, * you're strongly advised to have a look at * {@link IONIC.imagearchive.editors.GetCoverageChannelEditor#buildComponent} * for building such a component. *

* * @param {HTMLElement} component An HTML component */ IONIC.imagearchive.editors.GetCoverageChannelEditor = function (component) { IONIC.ui.InputEditor.call (this, component); }; IONIC.misc.extendType (IONIC.imagearchive.editors.GetCoverageChannelEditor, IONIC.ui.AbstractMultiValuedEditor); /** * Static factory for components that match the * {@link IONIC.imagearchive.editors.GetCoverageChannelEditor} * requirements. * * @param {IONIC.api.ui.DomHelper} dh A dom helper for building the * component. * * @param {IONIC.api.imagearchive.IAObject} iaObj An object that's * used to extract the channel info from. * * @return {HTMLElement} a component */ IONIC.imagearchive.editors.GetCoverageChannelEditor.buildComponent = function (dh, iaObj) { // --------- // Left list var left = dh.elt ("select"); left.multiple = true; left.ondblclick = function () { transfer.transferRight (); }; IONIC.misc.forEach (function (channel) { dh.mkOpt (left, channel); }, iaObj.getAxisSet ().getChannelAxe ().getValues ()); // ---------- // Right list var right = dh.elt ("select"); right.multiple = true; right.ondblclick = function () { transfer.transferLeft (); }; // ------ // Center var mkTo = function (what, functionName) { var img = dh.elt ("img"); img.src = IONIC.misc.getWebappBaseUrl () + "/images/imagearchive/getcoverage/" + what + ".gif"; img.onclick = function () { transfer [functionName] (); }; return img; }; var toRight = mkTo ("toright", "transferRight"); var allToRight = mkTo ("alltoright", "transferAllRight"); var toLeft = mkTo ("toleft", "transferLeft"); var allToLeft = mkTo ("alltoleft", "transferAllLeft"); var center = dh.elt ("table", dh.elt ("tbody", dh.elt ("tr", dh.elt ("td", toRight)), dh.elt ("tr", dh.elt ("td", allToRight)), dh.elt ("tr", dh.elt ("td", toLeft)), dh.elt ("tr", dh.elt ("td", allToLeft)))); var c = dh.elt ( "div", dh.elt ( "table", dh.elt ( "tbody", dh.elt ("tr", dh.elt ("th", dh.txt ("Selected")), dh.elt ("th"), dh.elt ("th", dh.txt ("Available"))), dh.elt ("tr", dh.elt ("td.channelSelector", left), dh.elt ("td", center), dh.elt ("td.channelSelector", right))))); var transfer = new OptionTransfer (left, right); transfer.setAutoSort (false); // avoid sorting of items. c.getSelectedChannelsSelector = function () { return left; }; return c; }; /** * Make a new instance * *

* This is the same as doing: *

var iaObj = ...; // get a IONIC.api.imagearchive.IAObject
var dh = ...; // get a IONIC.api.ui.DomHelper
var cpnt = IONIC.imagearchive.editors.GetCoverageChannelEditor.buildComponent (dh, iaObj);
var edtr = new IONIC.imagearchive.editors.GetCoverageChannelEditor (cpnt);
    
*

* * @param {IONIC.api.ui.DomHelper} dh A dom helper to build the * element * * @param {IONIC.api.imagearchive.IAObject} iaObj An object that's * used to extract the channel info from. * * @return {IONIC.imagearchive.editors.GetCoverageChannelEditor} */ IONIC.imagearchive.editors.GetCoverageChannelEditor.newInstance = function (dh, iaObj) { var cpnt = IONIC.imagearchive.editors.GetCoverageChannelEditor.buildComponent (dh, iaObj); return new IONIC.imagearchive.editors.GetCoverageChannelEditor (cpnt); }; /** * Returns the selected channels as a coma-separated string. */ IONIC.imagearchive.editors.GetCoverageChannelEditor.prototype.getValues = function () { var c = this.getComponent (); var leftSelector = c.getSelectedChannelsSelector (); var values = []; IONIC.misc.forEach (function (option) { values.push (option.value); }, leftSelector.options); return values.join (","); }; /*extern IONIC,_root,YAHOO*/ /** * @constructor * * @class * An {@link IONIC.api.imagearchive.IAObject} is an object in the * ImageArchive service. * *

* Note: You shouldn't build these objects yourself, but * rather use, for example, the * {@link IONIC.api.imagearchive.ImageArchiveSearchPanel} search * capabilities for retrieving these objects. *

* * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the server this object belongs to * @param {string} name The name of the object * @param {string} title The title of the object * @param {enumeration} type The type of the object *({@link IONIC.api.imagearchive.IAObject.TYPE_GRANULE}, * {@link IONIC.api.imagearchive.IAObject.TYPE_AGGREGATE}) * @param {string} path The path in the hierarchy * @param {string} uuid The id of the corresponding catalogue object */ IONIC.api.imagearchive.IAObject = function (serverRef, name, title, type, path, uuid) { this._sr= serverRef; this._n = name; this._tt= title; this._t = type; this._p = path; this._kwds = []; this._wcsok = false; this._wmsok = false; this._uuid = uuid; }; /** * Build an axis set. * * @constructor * * @class * An {@link IONIC.api.imagearchive.IAObject.AxisSet} describes the * set of axes an {@link IONIC.api.imagearchive.IAObject} knows. * *

* The {@link IONIC.api.imagearchive.IAObject.AxisSet} type provides * helper functions to handle the set of axes that can be used when * performing a GetCoverage request. *

* */ IONIC.api.imagearchive.IAObject.AxisSet = function () { this._otherAxes = []; }; /** * Build an axe. * * @constructor * * @class * An {@link IONIC.api.imagearchive.IAObject.AxisSet.Axe} describes * an axe known by an {@link IONIC.api.imagearchive.IAObject}. * *

* An axe has a name, a type * ( * {@link IONIC.api.imagearchive.IAObject.AxisSet.Axe#TYPE_RANGE} * or * {@link IONIC.api.imagearchive.IAObject.AxisSet.Axe#TYPE_ENUM}), * and an array of values. (in case the axe is of type range, the * array holds 2 values, which are the bounding minimum/maximum * values, and in case the axe is of type enumeration, the values * array holds N values, which are the enumeration entries) *

* * @param {string} name The name of the axe * * @param {int} type The type of the axe; either "range" or "enum" * * @param valuesType The type of the values, an entry in the * {@link IONIC.misc.PropertyType} enumeration * * @param values An array of values */ IONIC.api.imagearchive.IAObject.AxisSet.Axe = function (name, type, valuesType, values) { this._n = name; this._t = type; this._vt = valuesType; this._v = values.slice (); }; /** * An entry in the enumeration representing the type of axe. This * describes a "range" axe (with two values: minimum and maximum * bounds) */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_RANGE = 1; /** * An entry in the enumeration representing the type of axe. This * describes an "enum" axe (with N values) */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_ENUM = 2; /** * Get the name of this axe * * @return {string} the name */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.prototype.getName = function () { return this._n; }; /** * Get the type of this axe * * @return {int} the type; an entry in the * IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_* enumeration. */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.prototype.getType = function () { return this._t; }; /** * Get the array of values. * *

* This array is not meant to be modified! *

* * @return the array of values */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.prototype.getValues = function () { return this._v; }; /** * Get the data type of the entries in the array of values. * * @return the type of the values; an entry in the * {@link IONIC.misc.PropertyType} enumeration */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.prototype.getValuesType = function () { return this._vt; }; /** * Build an {@link IONIC.api.imagearchive.IAObject.AxisSet.Axe} from a * JavaScript object holding the necessary properties. * * @param {object} tfa A transport-formatted object holding the * information for building an * {@link IONIC.api.imagearchive.IAObject.AxisSet.Axe} * * @return {IONIC.api.imagearchive.IAObject.AxisSet.Axe} an axe object * * @private */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.fromTransportFormat = function (tfa) { var axe = new IONIC.api.imagearchive.IAObject.AxisSet.Axe ( tfa.name, IONIC.api.imagearchive.IAObject.AxisSet.Axe.typeStringToType (tfa.type), tfa.valuesType, tfa.values); return axe; }; /** * @ignore */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_MAPPING = { "enumeration" : IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_ENUM, "range" : IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_RANGE }; /** * @private */ IONIC.api.imagearchive.IAObject.AxisSet.Axe.typeStringToType = function (typeString) { var t = IONIC.api.imagearchive.IAObject.AxisSet.Axe.TYPE_MAPPING [typeString]; if (! t) { throw "Unexpected axe type: " + typeString; } return t; }; /** * Get the axe that's used to select what bands/axes to retrieve in a * GetCoverage request. * * @return {IONIC.api.imagearchive.IAObject.AxisSet.Axe} the channel * axe, or undefined if none present */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.getChannelAxe = function () { return this._chanAxe; }; /** * Set the axe that's used to select what bands/axes to retrieve in a * GetCoverage request. * * @param {IONIC.api.imagearchive.IAObject.AxisSet.Axe} axe The * channel axe * * @private */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.setChannelAxe = function (axe) { this._chanAxe = axe; }; /** * Get the axe that represents the null range. * *

* The "null" range, is the range of values that correspond to * transparency in an image (in case the image is requested through * WMS interface, or in empty data, in case the coverage is * requested through WCS interface *

* * @return {IONIC.api.imagearchive.IAObject.AxisSet.Axe} the null * axe, or undefined if none present */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.getNullAxe = function () { return this._nullAxe; }; /** * Set the axe that represents the null range. * * @param {IONIC.api.imagearchive.IAObject.AxisSet.Axe} axe The * channel axe * @private */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.setNullAxe = function (axe) { this._nullAxe = axe; }; /** * Get every axe but the "channel" nor the "null" ones. * * @return {IONIC.api.imagearchive.IAObject.AxisSet.Axe[]} an array of * axes */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.getOtherAxes = function () { return this._otherAxes; }; /** * Set the axes but the "channel" nor the "null" ones. * * @param {IONIC.api.imagearchive.IAObject.AxisSet.Axe[]} axes An * array of axes. * @private */ IONIC.api.imagearchive.IAObject.AxisSet.prototype.setOtherAxes = function (axes) { this._otherAxes = axes.slice (); }; /** * Build an {@link IONIC.api.imagearchive.IAObject.AxisSet} from a * JavaScript object holding the necessary properties. * * @param {object} tfas A transport-formatted object holding the * information for building an * {@link IONIC.api.imagearchive.IAObject.AxisSet} * * @return {IONIC.api.imagearchive.IAObject.AxisSet} an axe object * * @private */ IONIC.api.imagearchive.IAObject.AxisSet.fromTransportFormat = function (tfas) { var axisSet = new IONIC.api.imagearchive.IAObject.AxisSet (); if (tfas.channelAxis) { axisSet.setChannelAxe ( IONIC.api.imagearchive.IAObject.AxisSet.Axe.fromTransportFormat ( tfas.channelAxis)); } if (tfas.nullAxis) { axisSet.setNullAxe ( IONIC.api.imagearchive.IAObject.AxisSet.Axe.fromTransportFormat ( tfas.nullAxis)); } if (tfas.otherAxes) { axisSet.setOtherAxes ( IONIC.misc.mapcar1 (function (tfa) { return IONIC.api.imagearchive.IAObject.AxisSet.Axe.fromTransportFormat ( tfa); }, tfas.otherAxes)); } return axisSet; }; /** * An enumeration entry for the granule type */ IONIC.api.imagearchive.IAObject.TYPE_GRANULE = 1; /** * An enumeration entry for the aggregate type */ IONIC.api.imagearchive.IAObject.TYPE_AGGREGATE = 2; /** * Get the reference to the server this object belongs to. * * @return {IONIC.api.imagearchive.ServerRef} the server reference */ IONIC.api.imagearchive.IAObject.prototype.getServerRef = function () { return this._sr; }; /** * Get the name of the object * *

* The name is the ID of the object, as it is unique in an * ImageArchive server instance. *

* * @return {string} the name */ IONIC.api.imagearchive.IAObject.prototype.getName = function () { return this._n; }; /** * Get the uuid of the object * *

* The uuid of the object in the catalogue server. *

* * @return {string} the uuid */ IONIC.api.imagearchive.IAObject.prototype.getId = function () { return this._uuid; }; /** * Get the title of the object * * @return {string} the title */ IONIC.api.imagearchive.IAObject.prototype.getTitle = function () { return this._tt; }; /** * Get the type of the object * * @return {enumeration} the type ( * {@link IONIC.api.imagearchive.IAObject.TYPE_GRANULE}, ...) */ IONIC.api.imagearchive.IAObject.prototype.getType = function () { return this._t; }; /** * Is this object a granule? * * @return {boolean} true if this is an object of the * {@link IONIC.api.imagearchive.TYPE_GRANULE} type */ IONIC.api.imagearchive.IAObject.prototype.isGranule = function () { return this.getType () === IONIC.api.imagearchive.IAObject.TYPE_GRANULE; }; /** * Is this object an aggregate? * * @return {boolean} true if this is an object of the * {@link IONIC.api.imagearchive.TYPE_AGGREGATE} type */ IONIC.api.imagearchive.IAObject.prototype.isAggregate = function () { return this.getType () === IONIC.api.imagearchive.IAObject.TYPE_AGGREGATE; }; /** * Get the path of the object, in the hierarchy tree. * * @return {string} the path */ IONIC.api.imagearchive.IAObject.prototype.getPath = function () { return this._p; }; /** * Set the keywords for this object * * @param {string[]} keywords The keywords */ IONIC.api.imagearchive.IAObject.prototype.setKeywords = function (keywords) { this._kwds = keywords ? keywords.slice () : []; }; /** * Get the keywords for this object * * @return {string[]} the keywords */ IONIC.api.imagearchive.IAObject.prototype.getKeywords = function () { return this._kwds.slice (); }; /** * Set the WMS-availability of this object * * @param {boolean} flag A flag * @private */ IONIC.api.imagearchive.IAObject.prototype.setAvailabilityWMS = function (flag) { this._wmsok = flag; }; /** * Set the WCS-availability of this object * * @param {boolean} flag A flag * @private */ IONIC.api.imagearchive.IAObject.prototype.setAvailabilityWCS = function (flag) { this._wcsok = flag; }; /** * Is this object available as WMS? * * @return {boolean} true if this object is available as * WMS */ IONIC.api.imagearchive.IAObject.prototype.isAvailableAsWMS = function () { return this._wmsok; }; /** * Is this object available as WCS? * * @return {boolean} true if this object is available as * WCS */ IONIC.api.imagearchive.IAObject.prototype.isAvailableAsWCS = function () { return this._wcsok; }; /** * Is this object available as streamed raster? * *

* For a coverage to be available as streamed raster (i.e., ECWP, * JP2, ...), it is necessary that its decoder be "ECW" or "JP2". *

* * @return {boolean} true if this object is available as * streamed raster */ IONIC.api.imagearchive.IAObject.prototype.isAvailableAsStreamedRaster = function () { var streamingEnabled = "false" === "true"; var dn = (this.getDecoderName () || "").toUpperCase (); return streamingEnabled && ("ECW" === dn || "JP2" === dn); }; /** * Set the spatial extent for this object * * @param geom A geometry, from the {@link IONIC.api.geom} package. * @private */ IONIC.api.imagearchive.IAObject.prototype.setSpatialExtent = function (geom) { this._geom = geom; }; /** * Get the spatial extent for this object * * @return a geometry, from the {@link IONIC.api.geom} package, or * undefined if none */ IONIC.api.imagearchive.IAObject.prototype.getSpatialExtent = function () { return this._geom; }; /** * Set the temporal extent for this object * * @param tempExtent ... * @private */ IONIC.api.imagearchive.IAObject.prototype.setTemporalExtent = function (tempExtent) { this._tempExtent = tempExtent; }; /** * Get the temporal extent for this object * * @return the temporal extent, or undefined if none */ IONIC.api.imagearchive.IAObject.prototype.getTemporalExtent = function () { return this._tempExtent; }; /** * Set all the native bounding boxes that were defined for this * object. * * @param {IONIC.api.geom.Box[]} bboxes The array of bounding boxes * * @private */ IONIC.api.imagearchive.IAObject.prototype.setDefinedBoundingBoxes = function (bboxes) { this.bboxes = bboxes; }; /** * Get all the native bounding boxes that were defined for this * object. * *

* The returned array is not meant to be modified. *

* * @return {IONIC.api.geom.Box[]} the array of bounding boxes */ IONIC.api.imagearchive.IAObject.prototype.getDefinedBoundingBoxes = function () { return this.bboxes || []; }; /** * Set the children information for this object * * @param {object[]} childrenInfos The objects holding information * about the children. * @private */ IONIC.api.imagearchive.IAObject.prototype.setChildrenInfos = function (childrenInfos) { this._ci = childrenInfos; }; /** * Get the children information for this object * * @return {object[]} an array of objects having at least the * following property: name */ IONIC.api.imagearchive.IAObject.prototype.getChildrenInfos = function () { return this._ci; }; /** * Build the URL for fetching, as an image, the thumbnail * corresponding to this object with the given name. * * @param {int} width (optional) The width, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_WIDTH}. * @param {int} height (optional) The height, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_HEIGHT}. * * @see IONIC.imagearchive.ImageArchiveTool#getThumbnailUrl * @see IONIC.api.imagearchive.IAObject#loadThumbnailInImage */ IONIC.api.imagearchive.IAObject.prototype.getThumbnailUrl = function (width, height) { return (new IONIC.imagearchive.ImageArchiveTool (this.getServerRef ())). getThumbnailUrl ( this.getName (), width, height); }; /** * Set the {@link IONIC.api.imagearchive.IAObject.AxisSet} for this * object. * * @param {IONIC.api.imagearchive.IAObject.AxisSet} axisSet The axis * set */ IONIC.api.imagearchive.IAObject.prototype.setAxisSet = function (axisSet) { this._axisSet = axisSet; }; /** * Get the {@link IONIC.api.imagearchive.IAObject.AxisSet} for this * object. * * @return {IONIC.api.imagearchive.IAObject.AxisSet} the axis * set */ IONIC.api.imagearchive.IAObject.prototype.getAxisSet = function () { return this._axisSet; }; /** * Set the EPSG IDs in which a GetCoverage operation can * be performed on the ImageArchive, for this object. * * @param {int[]} srses The epsg IDs of the supported input srses * * @see #getGetCoverageRequestSRSes * * @private */ IONIC.api.imagearchive.IAObject.prototype.setGetCoverageRequestSRSes = function (srses) { this._getCovReqSrses = srses.slice (); }; /** * Get the array of EPSG IDs a GetCoverage operation * supports in input, for this object. * *

* The returned array is not meant to be modified. *

* * @return {int[]} the supported epsg IDs */ IONIC.api.imagearchive.IAObject.prototype.getGetCoverageRequestSRSes = function () { return this._getCovReqSrses || []; }; /** * Set the EPSG IDs in which the results of a * GetCoverage operation can be expressed, for this * object. * * @param {int[]} srses The epsg IDs of the supported output srses * * @see #getGetCoverageResponseSRSes * * @private */ IONIC.api.imagearchive.IAObject.prototype.setGetCoverageResponseSRSes = function (srses) { this._getCovRespSrses = srses.slice (); }; /** * Get the array of EPSG IDs a GetCoverage operation * supports in output, for this object. * *

* The returned array is not meant to be modified. *

* * @return {int[]} the supported epsg IDs */ IONIC.api.imagearchive.IAObject.prototype.getGetCoverageResponseSRSes = function () { return this._getCovRespSrses || []; }; /** * Set the list of formats supported by the GetCoverage * request, for this object. * * @param {string[]} formats The coverage formats * * @see #getCoverageTypes * * @private */ IONIC.api.imagearchive.IAObject.prototype.setCoverageTypes = function (formats) { this._covTypes = formats.slice (); }; /** * Set the list of formats supported by the GetCoverage * request, for this object. * *

* The returned array is not meant to be modified. *

* * @return {string[]} the supported coverage formats/types. */ IONIC.api.imagearchive.IAObject.prototype.getCoverageTypes = function () { return this._covTypes || []; }; /** * Set the list of interpolation methods supported by the * GetCoverage request, for this object. * * @param {string[]} interps The interpolation methods * * @see #getInterpolationMethods * * @private */ IONIC.api.imagearchive.IAObject.prototype.setInterpolationMethods = function (interps) { this._interps = interps.slice (); }; /** * Get the list of interpolation methods supported by the * GetCoverage request, for this object. * *

* The returned array is not meant to be modified. *

* * @return {string[]} the supported interpolation methods. */ IONIC.api.imagearchive.IAObject.prototype.getInterpolationMethods = function () { return this._interps || []; }; /** * Set the 'key-value pairs' field. * * @param {Array} kvPairs The key-value pairs * * @see #getKeyValuePairs * * @private */ IONIC.api.imagearchive.IAObject.prototype.setKeyValuePairs = function (kvPairs) { this._kvPairs = kvPairs; }; /** * Gets the key-value pairs. * *

* The returned array is not meant to be modified. *

* * @return {Array} the key-value pairs, or undefined if not set. */ IONIC.api.imagearchive.IAObject.prototype.getKeyValuePairs = function () { return this._kvPairs; }; /** * Set the decoder name. * * @param {string} decoderName The decoder name * * @see #getDecoderName * * @private */ IONIC.api.imagearchive.IAObject.prototype.setDecoderName = function (decoderName) { this.decoderName = decoderName; }; /** * Gets the decoder name. * * @return {string} the decoder name */ IONIC.api.imagearchive.IAObject.prototype.getDecoderName = function () { return this.decoderName; }; /** * Set the file URI (only makes sense for granules, not aggregates). * * @param {string} fileUri The file URI * * @see #getFileURI * * @private */ IONIC.api.imagearchive.IAObject.prototype.setFileURI = function (fileUri) { this.fileUri = fileUri; }; /** * Gets the file URI (only makes sense for granules, not aggregates). * * @return {string} the file URI */ IONIC.api.imagearchive.IAObject.prototype.getFileURI = function () { return this.fileUri; }; /** * Set the metadata URL. * * @param {string} metadata The URL for metadata */ IONIC.api.imagearchive.IAObject.prototype.setMetadataUrl = function (metadata) { this.metadata = metadata; }; /** * Gets the metadata URL. * * @return {string} The metadata URL. */ IONIC.api.imagearchive.IAObject.prototype.getMetadataUrl = function () { return this.metadata; }; /** * Loads the thumbnail for this object in the given image. * *

* This will set an onerror handler on the * <img>, that will be called if the given * object has no thumbnail, in order to display a nice * "thumbnail unavailable"-like image, rather than an ugly broken * image. *

* * @param {HTMLImgElement} img The HTML <img> * @param {int} width (optional) The width, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_WIDTH}. * @param {int} height (optional) The height, in pixels, of the * thumbnail. Defaults to * {@link IONIC.imagearchive.ImageArchiveTool.DEFAULT_THUMBNAIL_HEIGHT}. * * @see IONIC.api.imagearchive.IAObject#getThumbnailUrl * @see IONIC.imagearchive.ImageArchiveTool#getThumbnailUrl */ IONIC.api.imagearchive.IAObject.prototype.loadThumbnailInImage = function (img, width, height) { img.title = this.getTitle (); img.src = IONIC.misc.getWebappBaseUrl () + "/images/imagearchive/misc/loading_thumbnail.gif"; img.onerror = function () { img.src = IONIC.misc.getWebappBaseUrl () + "/images/imagearchive/misc/no_thumbnail.gif"; }; img.src = this.getThumbnailUrl (width, height); }; /** * Build an {@link IONIC.api.imagearchive.IAObject} from a JavaScript * object holding the necessary properties. * * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the server the object belongs to. * * @param {object} tfiao A transport-formatted object holding the * information for building an * {@link IONIC.api.imagearchive.IAObject} * * @return {IONIC.api.imagearchive.IAObject} an ImageArchive object */ IONIC.api.imagearchive.IAObject.fromTransportFormat = function (serverRef, tfiao) { var iao = new IONIC.api.imagearchive.IAObject ( serverRef, tfiao.name, tfiao.title, IONIC.api.imagearchive.IAObject.typeStringToType (tfiao.type), tfiao.path, tfiao.uuid); iao.setKeywords(tfiao.keywords); iao.setAvailabilityWMS(tfiao.availabilityWMS); iao.setAvailabilityWCS(tfiao.availabilityWCS); iao.setMetadataUrl(tfiao.metadata); var se = tfiao.spatialExtent; if (se) { iao.setSpatialExtent (IONIC.geom.JGTFTool.JGTFToGeometry (se)); } if (tfiao.temporalExtent) { iao.setTemporalExtent (tfiao.temporalExtent); } if (tfiao.keyValuePairs) { iao.setKeyValuePairs (tfiao.keyValuePairs); } if (tfiao.childrenInfos) { iao.setChildrenInfos (tfiao.childrenInfos.slice ()); } if (tfiao.axes) { iao.setAxisSet ( IONIC.api.imagearchive.IAObject.AxisSet.fromTransportFormat ( tfiao.axes)); } if (tfiao.requestCRSes) { iao.setGetCoverageRequestSRSes (tfiao.requestCRSes); } if (tfiao.responseCRSes) { iao.setGetCoverageResponseSRSes (tfiao.responseCRSes); } if (tfiao.coverageTypes) { iao.setCoverageTypes (tfiao.coverageTypes); } if (tfiao.interpolationTypes) { iao.setInterpolationMethods (tfiao.interpolationTypes); } if (tfiao.decoderName) { iao.setDecoderName (tfiao.decoderName); } if (tfiao.bboxes) { // Add the defined bboxes iao.setDefinedBoundingBoxes (IONIC.misc.mapcar1 (function (bbox) { return IONIC.api.geom.Box.fromValues (bbox); }, tfiao.bboxes)); } if (tfiao.fileUri) { iao.setFileURI (tfiao.fileUri); } return iao; }; /** * @ignore */ IONIC.api.imagearchive.IAObject.TYPE_MAPPING = { "Granule" : IONIC.api.imagearchive.IAObject.TYPE_GRANULE, "Aggregate" : IONIC.api.imagearchive.IAObject.TYPE_AGGREGATE }; /** * @private */ IONIC.api.imagearchive.IAObject.typeStringToType = function (typeString) { var t = IONIC.api.imagearchive.IAObject.TYPE_MAPPING [typeString]; if (! t) { throw "Unexpected object type: " + typeString; } return t; }; /** * @constructor * * @class * This class allows to create and display a popup window that describes an IAObject. When a * popup is created, it is first hidden and must be made visible using {@link #show}. * * @extends IONIC.imagearchive.AbstractPopup * * @param {IONIC.api.ui.DomHelper} A DOM helper. * @param {IONIC.api.imagearchive.IAObject} iaObject (Optional.) The object to depict. If not * set, must be set afterwards using {@link #setContent}. * @param {IONIC.api.maps.Map} A map. (Optional.) If set, the footprint of the IAObject will be * displayed when the {@link show} method is called. */ IONIC.api.imagearchive.IAObjectPopup = function(dh, iaObject, map) { IONIC.imagearchive.AbstractPopup.call(this, dh); this.map = map; if (iaObject) this.setContent(iaObject); }; IONIC.misc.extendType (IONIC.api.imagearchive.IAObjectPopup, IONIC.imagearchive.AbstractPopup); /** * Sets the object represented by this popup. * * @param {IONIC.api.imagearchive.IAObject} iaObject The object. */ IONIC.api.imagearchive.IAObjectPopup.prototype.setContent = function(iaObject) { IONIC.imagearchive.AbstractPopup.prototype.setContent.call(this, iaObject); var elt = this.getHTMLElement(); var dh = this.dh; dh.clr (elt); var mkTextLine = function(label, text, labelClass) { dh.append(elt, dh.elt("div" + (labelClass ? ("." + labelClass) : ""), dh.elt("span", dh.txt(label + ": ")), dh.elt("span", dh.txt(text)))); }; mkTextLine("Name", iaObject.getName(), "name"); mkTextLine("Title", iaObject.getTitle(), "title"); if (iaObject.getSpatialExtent()) mkTextLine("Spatial extent", iaObject.getSpatialExtent().getEnvelope().commaRepresentation(), "bbox"); if (iaObject.getTemporalExtent()) mkTextLine("Temporal extent", iaObject.getTemporalExtent().toString(), "temporal"); mkTextLine("Keywords", iaObject.getKeywords().join(", "), "keywords"); var thumb = dh.elt("img.thumbnail"); iaObject.loadThumbnailInImage(thumb); dh.append(elt, thumb); }; /** * Shows the popup. The (optional) delay is applied. */ IONIC.api.imagearchive.IAObjectPopup.prototype.show = function() { IONIC.imagearchive.AbstractPopup.prototype.show.call(this); // Display footprint var se = this.displayedObject.getSpatialExtent(); if (this.map && se) this.map.showGeometry(se, IONIC.api.imagearchive.IAObjectPopup.FOOTPRINT_DRAWING_OPTIONS); }; /** * Hides the popup. */ IONIC.api.imagearchive.IAObjectPopup.prototype.hide = function() { IONIC.imagearchive.AbstractPopup.prototype.hide.call(this); if (this.map) this.map.clearGeometryEditingLayerDescriptor(); }; /** * Destroys the popup. */ IONIC.api.imagearchive.IAObjectPopup.prototype.destroy = function() { IONIC.imagearchive.AbstractPopup.prototype.destroy.call(this); if (this.map) this.map.clearGeometryEditingLayerDescriptor(); }; IONIC.api.imagearchive.IAObjectPopup.FOOTPRINT_DRAWING_OPTIONS = new IONIC.api.maps.Map.DrawingOptions(.5, "#000000", 1.0, // stroke "#dd0000", 0.2, // fill null, null, null); /** * @constructor * * @class * This class allows to create and display a popup window that describes a WFS server. When a * popup is created, it is first hidden and must be made visible using {@link #show}. * * @extends IONIC.imagearchive.AbstractPopup * * @param {IONIC.api.ui.DomHelper} A DOM helper. * @param {object} wfsObject (Optional.) The object to depict. If not * set, must be set afterwards using {@link #setContent}. * @param {IONIC.api.maps.Map} A map. (Optional.) If set, the footprint of the object will be * displayed when the {@link show} method is called. */ IONIC.api.imagearchive.WfsPopup = function(dh, wfsObject, map) { IONIC.imagearchive.AbstractPopup.call(this, dh); this.map = map; if (wfsObject) this.setContent(wfsObject); }; IONIC.misc.extendType (IONIC.api.imagearchive.WfsPopup, IONIC.imagearchive.AbstractPopup); /** * Sets the object represented by this popup. * * @param {object} wfsObject The object. */ IONIC.api.imagearchive.WfsPopup.prototype.setContent = function(wfsObject) { IONIC.imagearchive.AbstractPopup.prototype.setContent.call(this, wfsObject); var elt = this.getHTMLElement(); var dh = this.dh; dh.clr(elt); var name = wfsObject.name; var keywords = wfsObject.keywords ? wfsObject.keywords.join(", ") : undefined; var bbox = wfsObject.footprint ? wfsObject.footprint.getEnvelope ().commaRepresentation () : undefined; dh.append(elt, dh.txt(name), dh.elt("br")); if (keywords) dh.append(elt, dh.txt(keywords), dh.elt("br")); if (bbox) dh.append(elt, dh.txt("Envelope: "), dh.txt(bbox), dh.elt("br")); if (wfsObject.wfsUrl) dh.append(elt, dh.txt("URL: "), dh.txt(wfsObject.wfsUrl), dh.elt("br")); if (wfsObject.layerName) dh.append(elt, dh.txt("LayerName: "), dh.txt(wfsObject.layerName), dh.elt("br")); }; /** * Shows the popup. The (optional) delay is applied. */ IONIC.api.imagearchive.WfsPopup.prototype.show = function() { IONIC.imagearchive.AbstractPopup.prototype.show.call(this); // Display footprint var se = this.displayedObject.footprint; if (this.map && se) this.map.showGeometry(se, IONIC.api.imagearchive.WfsPopup.FOOTPRINT_DRAWING_OPTIONS); }; /** * Hides the popup. */ IONIC.api.imagearchive.WfsPopup.prototype.hide = function() { IONIC.imagearchive.AbstractPopup.prototype.hide.call(this); if (this.map) this.map.clearGeometryEditingLayerDescriptor(); }; /** * Destroys the popup. */ IONIC.api.imagearchive.WfsPopup.prototype.destroy = function() { IONIC.imagearchive.AbstractPopup.prototype.destroy.call(this); if (this.map) this.map.clearGeometryEditingLayerDescriptor(); }; IONIC.api.imagearchive.WfsPopup.FOOTPRINT_DRAWING_OPTIONS = new IONIC.api.maps.Map.DrawingOptions(1, "#000000", 1.0, // stroke "#dd0000", 0.2, // fill null, null, null); /** * @constructor * * @class * A map specialized in order to accept {@link IONIC.api.imagearchive.IAObject} for rendering. * * @extends IONIC.api.maps.Map * * @param {string} serverWmsUrl The URL of the IA server that will be * used to access it as a WMS. * * @param {string} streamedRasterAccessBaseUrl The base of the URLs * for accessing the ECW/JPEG2000 layers in a fast way. * * @param {HTMLElement} htmlElt (Optional) The HTML element where the * map has to be depicted. If omitted, the map will not be inserted * into the HTML DOM, and you'll have to do it yourself. (See {@link * #getHTMLView}) * * @param {object} win The HTML window in which this view's HTML * element is meant to be inserted. (optional) * * @param {int} width (Optional) The width (in pixels) of the * IONIC.api.maps.Map's HTML element; if omitted, a default width is * assigned. * * @param {int} height (Optional) The height (in pixels) of the * IONIC.api.maps.Map's HTML element; if omitted, a default height is * assigned. */ IONIC.api.imagearchive.ImageArchiveMap = function (serverWmsUrl, streamedRasterAccessBaseUrl, htmlElt, win, width, height) { IONIC.api.maps.Map.call (this, htmlElt, win, width, height); this._serverWmsUrl = serverWmsUrl; this.streamedRasterAccessBaseUrl = streamedRasterAccessBaseUrl; }; IONIC.misc.extendType (IONIC.api.imagearchive.ImageArchiveMap, IONIC.api.maps.Map); /** * Return the URL at which the ImageArchive server can be reached as a * WMS. * * @return {string} the url */ IONIC.api.imagearchive.ImageArchiveMap.prototype.getServerWMSUrl = function () { return this._serverWmsUrl; }; /** * Return the base of the URLs for accessing raster at high * speed. * * @return {string} the base of the url */ IONIC.api.imagearchive.ImageArchiveMap.prototype.getStreamedRasterAccessBaseUrl = function () { return this.streamedRasterAccessBaseUrl; }; /** * Adds the coverage corresponding to an {@link IONIC.api.imagearchive.IAObject} to this map. * * @param {IONIC.api.imagearchive.IAObject} iaObject The object to depict. * @param {function} callback (Optional) The callback called once the coverage has been added to the * map. It takes one argument: the {@link IONIC.api.maps.WMSSSLayer} corresponding to this coverage. */ IONIC.api.imagearchive.ImageArchiveMap.prototype.addCoverage = function (iaObject, callback) { var ld, tflo, fileUri, parts, config, bboxes; if (iaObject.isAvailableAsWMS () || iaObject.isAvailableAsStreamedRaster ()) { // If the SRSes do match, let's add already.. if (iaObject.getSpatialExtent ().getEnvelope ().epsgId === this.getSrs ()) { bboxes = [ iaObject.getSpatialExtent ().getEnvelope () ].concat (iaObject.getDefinedBoundingBoxes ().slice ()); // The layer description tflo = { name : iaObject.getName (), serviceUrl : this.getServerWMSUrl (), serviceVersion : "1.3.0", title : iaObject.getName (), bboxes : bboxes, nativelySupportedSrs : IONIC.misc.mapcar1 (function (box) { return box.epsgId; }, iaObject.getDefinedBoundingBoxes ()), metadata : iaObject.getMetadataUrl () ? [iaObject.getMetadataUrl ()] : [], getFeatureInfoFormats : [], queryable : true, displayable : true, scaleRange : null, // imageFormats : ,[????????????????], styles : [], serviceType : IONIC.api.maps.WMSSSLayer.SERVICE_TYPE }; if (iaObject.isAvailableAsStreamedRaster ()) { fileUri = iaObject.getFileURI () || ""; // Typically, a fileUri has "\\" or // "/" in it. Let's only keep the file // name. parts = fileUri.split ("\\"); fileUri = parts [parts.length - 1]; parts = fileUri.split ("/"); fileUri = parts [parts.length - 1]; // Patch "tflo" for streamed ECWP/JP2 // access tflo.serviceType = IONIC.api.maps.ECWPSSLayer.SERVICE_TYPE; tflo.ecwpAccessUrl = this.getStreamedRasterAccessBaseUrl () + "/" + fileUri; // The layer config config = { login : this.getStreamedRasterAccessLogin (), password : this.getStreamedRasterAccessPassword () }; } var ld = IONIC.api.maps.LayerDescriptor.fromTransportFormat (tflo, config); // If the layer is accessed using the ERMapper plugin, we add the session id // to the URL; it will be used to perform authentication if (iaObject.isAvailableAsStreamedRaster ()) { ld.forEachServerSideLayer (function (ssLayer) { var cookie = IONIC.misc.getCookie ("JSESSIONID"); if (cookie) { ssLayer.setUrlSuffix (cookie); } }); } this.addLayerDescriptor (ld); if (callback) { callback (ld); } } else { // ..otherwise, let's retrieve it in the // proper SRS this.addCoverageByName (iaObject.getName (), callback); } } else { throw "Coverage is not available as a WMS, ECWP or JP2."; } }; /** * Adds the coverage corresponding to an {@link IONIC.api.imagearchive.IAObject} to this map. * * @param {string} name The name of the object to depict. * @param {function} callback (Optional) The callback called once the coverage has been added to the * map. It takes one argument: the {@link IONIC.api.maps.WMSSSLayer} corresponding to this coverage. */ IONIC.api.imagearchive.ImageArchiveMap.prototype.addCoverageByName = function (name, callback) { var self = this; this.getImageArchiveTool ().withCoverageByName ( name, this.getSrs (), function (iaObject) { self.addCoverage (iaObject, callback); }, true); }; /** * Set the login/password for accessing the streamed raster access * server of the image archive. * * @param {string} login The login * * @param {string} password The password */ IONIC.api.imagearchive.ImageArchiveMap.prototype.setStreamedRasterAccessCredentials = function (login, password) { this.streamedRasterAccessLogin = login; this.streamedRasterAccessPassword = password; }; /** * Get the login for accessing the streamed raster access * server of the image archive. * * @return {string} the login */ IONIC.api.imagearchive.ImageArchiveMap.prototype.getStreamedRasterAccessLogin = function () { return this.streamedRasterAccessLogin; }; /** * Get the password for accessing the streamed raster access * server of the image archive. * * @return {string} the password */ IONIC.api.imagearchive.ImageArchiveMap.prototype.getStreamedRasterAccessPassword = function () { return this.streamedRasterAccessPassword; }; /** * @constructor * * @class * This default implementation of a * {@link IONIC.ui.AbstractObjectRenderer} will * create <tr>, and therefore * is meant to be used with a * {@link IONIC.api.imagearchive.TableResultsHandler} * * @extends IONIC.ui.AbstractObjectRenderer * *

* This renderer will create mouse-sensitive rows that, when * hovered, will display a popup with the object information. *

*

* In case the parent * {@link IONIC.api.imagearchive.TableResultsHandler} has an * associated {@link IONIC.api.maps.Map}, it will also display the * geometry of the objects on the map. *

*

* In case the parent * {@link IONIC.api.imagearchive.TableResultsHandler} has an * associated * {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel}, it * will also display, for each result that can be retrieved through * the panel, an icon to import it into the panel for retrieval. *

*/ IONIC.api.imagearchive.DefaultTableRowRenderer = function () { }; IONIC.misc.extendType (IONIC.api.imagearchive.DefaultTableRowRenderer, IONIC.ui.AbstractObjectRenderer); /** * Create an HTML <tr>, ready to be embedded in the * {@link IONIC.api.imagearchive.TableResultsHandler}'s current page's * <table> * * @param {IONIC.api.imagearchive.TableResultsHandler} * parentResultsHandler The instance of * {@link IONIC.api.imagearchive.TableResultsHandler} that called * this renderer * @param {IONIC.api.imagearchive.IAObject} iaobj An object in the * ImageArchive server * @return {HTMLTrElement} the <tr> to be embedded into the * parent {@link IONIC.api.imagearchive.TableResultsHandler} */ IONIC.api.imagearchive.DefaultTableRowRenderer.prototype.render = function (parentResultsHandler, iaobj) { var dh = parentResultsHandler.getDomHelper (); var typeImg = dh.elt ("img"); typeImg.src = IONIC.misc.getWebappBaseUrl () + "/images/imagearchive/search/" + (iaobj.isAggregate () ? "aggregate" : "granule") + (IONIC.api.imagearchive.DefaultTableRowRenderer.useSmallIcons ? "-small" : "") + ".gif"; var addedToMapElt = dh.elt ("span.addedToMapMarker"); var titleElt = dh.elt ("td", addedToMapElt, dh.txt (iaobj.getName ())); var row = dh.elt ( "tr.resultEntry", dh.elt ("td", typeImg), // type (aggregate/granule) titleElt); titleElt.displayedObject = iaobj; titleElt.displayedObjectHolder = { iaObject: iaobj, getIAObject: function (callback, full) { // Not implemented: taking care of 'full' argument. It should not be necessary callback(iaobj); } }; titleElt.onclick = function () { SearchModule.getDetailPanel ().renderDetailsByName (iaobj.getName ()); }; if (this.htmlDecorator) { this.htmlDecorator.addElements ([titleElt]); } var importCov; var getCoveragePanel = parentResultsHandler.getAssociatedGetCoveragePanel (); if (getCoveragePanel) { if (iaobj.isAvailableAsWCS ()) { importCov = dh.elt ("input.importCoverage"); importCov.type = "button"; importCov.value = "Get coverage"; importCov.onclick = function () { getCoveragePanel.loadCoverageDescriptionByName (iaobj.getName ()); }; dh.append (row, dh.elt ("td", importCov)); } else { dh.append (row, dh.elt ("td", dh.txt (" "))); } } var displayMap = parentResultsHandler.getAssociatedDisplayMap (); if (displayMap) { if (iaobj.isAvailableAsWMS ()) { importCov = dh.elt ("input.importCoverage"); importCov.type = "button"; importCov.value = "Add to map"; importCov.onclick = function () { displayMap.addCoverage (iaobj); }; dh.append (row, dh.elt ("td", importCov)); } else { dh.append (row, dh.elt ("td", dh.txt (" "))); } } var self = this; row.onmouseover = function (e) { var popup = self.retrieveHoverPopup (parentResultsHandler, parentResultsHandler.getAssociatedMap ()); IONIC.api.imagearchive.DefaultTableRowRenderer.onMouseOverHandler (popup, iaobj); e = e || event; var evt = JSToolbox.Event; var mx = evt.getMouseX (e); var my = evt.getMouseY (e); }; row.onmouseout = function (e) { e = e || event; var popup = self.retrieveHoverPopup (parentResultsHandler, parentResultsHandler.getAssociatedMap ()); IONIC.api.imagearchive.DefaultTableRowRenderer.onMouseOutHandler (popup); }; this.renderFootprint (iaobj); return row; }; /** * Adds a 'decorator', i.e. an object that can be aware of the generation of HTML elements * representing an ImageArchive object. * @param {object} htmlDecorator The decorator. It must have two properties: addElements * that is a function with one argument: an array of HTMLElements. Each such HTML element * will have a iaObjectName (string) property and an optional iaObject * (object) property. The second property is deleteElement, which is symetrical to * addElements and take the same argument. */ IONIC.api.imagearchive.DefaultTableRowRenderer.prototype.setHtmlDecorator = function (htmlDecorator) { this.htmlDecorator = htmlDecorator; }; /** * @private */ IONIC.api.imagearchive.DefaultTableRowRenderer.onMouseOverHandler = function (popup, iaobj) { popup.setContent (iaobj); popup.show (); }; /** * @private */ IONIC.api.imagearchive.DefaultTableRowRenderer.onMouseOutHandler = function(popup) { popup.hide (); }; /** * @ignore */ IONIC.api.imagearchive.DefaultTableRowRenderer.POPUPTIMEOUT = 300; /** * Get the <div>, that will be used as a popup, displaying * information about the result. * * @param {IONIC.misc.AbstractResultsHandler} parentResultsHandler The * instance of {@link IONIC.misc.AbstractResultsHandler} that called * this renderer * @return {HTMLDivElement} * @private */ IONIC.api.imagearchive.DefaultTableRowRenderer.prototype.retrieveHoverPopup = function (parentResultsHandler, map) { var dh, s; if (! parentResultsHandler.hoverPopup) { dh = parentResultsHandler.getDomHelper (); parentResultsHandler.hoverPopup = new IONIC.api.imagearchive.IAObjectPopup(dh, null, map); parentResultsHandler.hoverPopup.setDelay(IONIC.api.imagearchive.DefaultTableRowRenderer.POPUPTIMEOUT); } return parentResultsHandler.hoverPopup; }; /** * Draws the footprint of the object. Requires a layer to draw the footprint to; see {@link #setFootprintLayer}. * * @param {IONIC.api.imagearchive.IAObject} iaObject The object to depict. * @private */ IONIC.api.imagearchive.DefaultTableRowRenderer.prototype.renderFootprint = function (iaObject) { if (!this.footprintLayer || !iaObject.getSpatialExtent ()) { return; } var drawingOptions = iaObject.isAggregate () ? IONIC.api.imagearchive.DefaultTableRowRenderer.FOOTPRINT_AGGREGATE_DRAWING_OPTIONS : IONIC.api.imagearchive.DefaultTableRowRenderer.FOOTPRINT_GRANULE_DRAWING_OPTIONS; this.footprintLayer.addGeometry (iaObject.getSpatialExtent (), drawingOptions); }; /** * Allows to add a {@link IONIC.geom.edit.GEditLayerDescriptor} layer that will be used to draw the * footprint of each result. * * @param {IONIC.geom.edit.GEditLayerDescriptor} layer The layer. */ IONIC.api.imagearchive.DefaultTableRowRenderer.prototype.setFootprintLayer = function (layer) { this.footprintLayer = layer; }; IONIC.api.imagearchive.DefaultTableRowRenderer.FOOTPRINT_GRANULE_DRAWING_OPTIONS = new IONIC.api.maps.Map.DrawingOptions(.5, "#880000", .5); IONIC.api.imagearchive.DefaultTableRowRenderer.FOOTPRINT_AGGREGATE_DRAWING_OPTIONS = new IONIC.api.maps.Map.DrawingOptions(.5, "#880000", .7); /** * @private */ IONIC.api.imagearchive.DefaultTableRowRenderer.useSmallIcons = true; /** * @constructor * * @class * This default implementation of a * {@link IONIC.ui.AbstractObjectRenderer} will * create <tr>, and therefore * is meant to be used with a * {@link IONIC.api.imagearchive.TableResultsHandler}. It renders objects * returned by a search * * @extends IONIC.ui.AbstractObjectRenderer * *

* This renderer will create mouse-sensitive rows that, when * hovered, will display a popup with the object information. *

*

* In case the parent * {@link IONIC.api.imagearchive.TableResultsHandler} has an * associated {@link IONIC.api.maps.Map}, it will also display the * geometry of the objects on the map. *

*

* In case the parent * {@link IONIC.api.imagearchive.TableResultsHandler} has an * associated * {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel}, it * will also display, for each result that can be retrieved through * the panel, an icon to import it into the panel for retrieval. *

*/ IONIC.api.imagearchive.WfsTableRowRenderer = function () { this.htmlDecorator = null; }; IONIC.misc.extendType (IONIC.api.imagearchive.WfsTableRowRenderer, IONIC.ui.AbstractObjectRenderer); /** * Create an HTML <tr>, ready to be embedded in the * {@link IONIC.api.imagearchive.TableResultsHandler}'s current page's * <table>. * * @param {IONIC.api.imagearchive.TableResultsHandler} * parentResultsHandler The instance of * {@link IONIC.api.imagearchive.TableResultsHandler} that called * this renderer * * @param {object} wfsObject An object describing a WFS service. * * @return {HTMLTrElement} the <tr> to be embedded into the * parent {@link IONIC.api.imagearchive.TableResultsHandler} */ IONIC.api.imagearchive.WfsTableRowRenderer.prototype.render = function (parentResultsHandler, wfsObject) { var dh = parentResultsHandler.getDomHelper (); var typeImg = dh.elt ("img"); typeImg.src = IONIC.misc.getWebappBaseUrl () + "/images/imagearchive/search/wfs" + (IONIC.api.imagearchive.DefaultTableRowRenderer.useSmallIcons ? "-small" : "") + ".gif"; var displayMap = parentResultsHandler.getAssociatedDisplayMap (); var iaTool = parentResultsHandler.getAssociatedIATool (); var titleElt = dh.elt ("td", dh.txt (wfsObject.name)); var row = dh.elt ("tr", dh.elt ("td", typeImg), titleElt); if (this.htmlDecorator) { titleElt.wfsObject = wfsObject; this.htmlDecorator.addElements ([titleElt]); } if (iaTool) { var iso19115Button = this.makeIso19115Button (dh, iaTool, wfsObject); dh.append (row, dh.elt ("td", iso19115Button)) } if (displayMap && wfsObject.wmsUrl) { var wmsButton = this.makeWmsButton (dh, wfsObject, displayMap); dh.append (row, dh.elt ("td", wmsButton)); } if (displayMap && wfsObject.wfsUrl) { var wfsButton = this.makeWfsButton (dh, wfsObject, displayMap); dh.append (row, dh.elt ("td", wfsButton)); } row.onmouseover = function (e) { e = e || event; row.popup = new IONIC.api.imagearchive.WfsPopup (dh, wfsObject, displayMap); row.popup.show (); }; row.onmouseout = function (e) { e = e || event; if (row.popup) { row.popup.destroy (); row.popup = null; } }; return row; }; /** * Adds a 'decorator', i.e. an object that can be aware of the generation of HTML elements * representing WFS service. * @param {object} htmlDecorator The decorator. It must have two properties: addElements * that is a function with one argument: an array of HTMLElements. Each such HTML element * will have a wfsObject (object) property. The second property is deleteElement, * which is symetrical to addElements and take the same argument. */ IONIC.api.imagearchive.WfsTableRowRenderer.prototype.setHtmlDecorator = function (htmlDecorator) { this.htmlDecorator = htmlDecorator; }; /** * Builds the 'add WFS as WMS to map' button. * * @param {IONIC.api.ui.DomHelper} dh A dom helper. * @param {object} wfsObject The object representing the WFS service. * @param {IONIC.api.imagearchive.ImageArchiveMap} The map where the WFS should be added. * * @private */ IONIC.api.imagearchive.WfsTableRowRenderer.prototype.makeWmsButton = function (dh, wfsObject, displayMap) { wmsButton = dh.elt ("input.wfsToMapAsWms"); wmsButton.type = "button"; wmsButton.value = "Add to map as WMS"; wmsButton.onclick = function () { displayMap.addWMSLayers (wfsObject.wmsUrl, wfsObject.layerName); } return wmsButton; }; /** * Builds the 'add WFS as WFS to map' button. * * @param {IONIC.api.ui.DomHelper} dh A dom helper. * @param {object} wfsObject The object representing the WFS service. * @param {IONIC.api.imagearchive.ImageArchiveMap} The map where the WFS should be added. * * @private */ IONIC.api.imagearchive.WfsTableRowRenderer.prototype.makeWfsButton = function (dh, wfsObject, displayMap) { wfsButton = dh.elt ("input.wfsToMapAsWms"); wfsButton.type = "button"; wfsButton.value = "Add to map"; wfsButton.onclick = function () { var providerDiscovery = new IONIC.api.maps.ProviderDiscoveryTool (displayMap); providerDiscovery.withAddedWFSLayers (wfsObject.wfsUrl, [ wfsObject.layerName ]); } return wfsButton; }; /** * Builds the 'add WFS as WMS to map' button. * * @param {IONIC.api.ui.DomHelper} dh A dom helper. * @param {IONIC.imagearchive.ImageArchiveTool} The tool used to access metadata. * @param {object} wfsObject The object representing the WFS service. * * @private */ IONIC.api.imagearchive.WfsTableRowRenderer.prototype.makeIso19115Button = function (dh, iaTool, wfsObject) { isoButton = dh.elt ("input.wfsIso19115"); isoButton.type = "button"; isoButton.value = "ISO19115"; isoButton.onclick = function () { open (iaTool.getWfsISO19115SearchUrl(wfsObject.id), "ISO19115", "width=600,height=400,scrollbars=1,resizable=1"); } return isoButton; }; /** * @private */ IONIC.api.imagearchive.WfsTableRowRenderer.useSmallIcons = IONIC.api.imagearchive.DefaultTableRowRenderer.useSmallIcons; /** * @constructor * * @class * A {@link IONIC.api.imagearchive.TableResultsHandler} can be passed * to the {@link IONIC.api.imagearchive.ImageArchiveSearchPanel} and * handles the results from a search on an image archive server. * *

* This handler builds a notebook, with each page of which holding a * <table> with the results. The table * is filled with the <tr> produced by the * {@link IONIC.ui.AbstractObjectRenderer} *

*

* If the renderer is unspecified, instance of this type will use a * {@link IONIC.api.imagearchive.DefaultTableRowRenderer} * to render the results. If you want to override the default * behaviour, you'll need to provide your own * {@link IONIC.ui.AbstractObjectRenderer}. *

* * @extends IONIC.api.ui.NotebookResultsHandler * * @param {HTMLElement} htmlElt The HTML element (or it's ID) in which * the table will be built * @param {IONIC.api.ui.DomHelper} dh A dom helper instance * @param {IONIC.ui.AbstractObjectRenderer} renderer (optional) A * renderer to use for the results * @param {int} itemsPerPage (optional) The number of items per page */ IONIC.api.imagearchive.TableResultsHandler = function (htmlElt, dh, renderer, itemsPerPage) { var self = this; IONIC.api.ui.NotebookResultsHandler.call (this, htmlElt, dh, renderer || new IONIC.api.imagearchive.DefaultTableRowRenderer (), itemsPerPage); }; IONIC.misc.extendType (IONIC.api.imagearchive.TableResultsHandler, IONIC.api.ui.NotebookResultsHandler); /** * Create a <table> to be the top element of a page * * @return {HTMLTableElement} the table */ IONIC.api.imagearchive.TableResultsHandler.prototype.createPageContents = function () { var dh = this.getDomHelper (); return dh.elt ("table", dh.elt ("tbody")); }; /** * Injects the HTML fragment in the tab view's container. * * @param {YAHOO.widget.Tab} tab The current page * @param {HTMLElement} html The HTML to be embedded into the page */ IONIC.api.imagearchive.TableResultsHandler.prototype.injectHTMLResult = function (tab, html) { var dh = this.getDomHelper (); var table = tab.hackGetContents (); var tbd = table.getElementsByTagName ("tbody") [0]; dh.append (tbd, html); }; /** * Get the {@link IONIC.api.maps.Map} that is associated to this * instance. * * @return {IONIC.api.maps.Map} the associated map */ IONIC.api.imagearchive.TableResultsHandler.prototype.getAssociatedMap = function () { return this._map; }; /** * Set the {@link IONIC.api.maps.Map} that is associated to this * instance. * *

* Attaching a {@link IONIC.api.maps.Map} to an instance of this * type will allow the delegate types to work with it. In other * words, take the * {@link IONIC.api.imagearchive.DefaultTableRowRenderer} for * example: If it finds a map associated to this results handler, it * will be able to show the geometries of the objects on the * map. Ain't that cool? *

* * @param {IONIC.api.maps.Map} map The map to be associated to this * instance. */ IONIC.api.imagearchive.TableResultsHandler.prototype.setAssociatedMap = function (map) { this._map = map; }; /** * Get the {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} * that is associated to this instance. * * @return {IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} the * associated "GetCoverage" panel */ IONIC.api.imagearchive.TableResultsHandler.prototype.getAssociatedGetCoveragePanel = function () { return this._covPanel; }; /** * Set the {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} * that is associated to this instance. * *

* Attaching a * {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} to an * instance of this type will allow the delegate types to work with * it. In other words, take the * {@link IONIC.api.imagearchive.DefaultTableRowRenderer} for * example: If it finds a GetCoverage associated to this results * handler, the results will be retrievable through that panel. *

* * @param {IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} * coveragePanel The panel */ IONIC.api.imagearchive.TableResultsHandler.prototype.setAssociatedGetCoveragePanel = function (coveragePanel) { this._covPanel = coveragePanel; }; /** * Get the {@link IONIC.api.maps.Map} that is associated to this instance. This map is used to * display coverages. * * @return {IONIC.api.maps.Map} the associated display map. */ IONIC.api.imagearchive.TableResultsHandler.prototype.getAssociatedDisplayMap = function () { return this._displayMap; }; /** * Set the {@link IONIC.api.maps.Map} that is associated to this instance. This map is used to * display coverages. * * @param {IONIC.api.maps.Map} map The map to use to display coverages */ IONIC.api.imagearchive.TableResultsHandler.prototype.setAssociatedDisplayMap = function (map) { this._displayMap = map; }; /** * Get the {@link IONIC.imagearchive.ImageArchiveTool} that is associated to this instance. * It can be used to fetch information related to the displayed results, such as metadata. * * @return {IONIC.imagearchive.ImageArchiveTool} the associated display map. * @private */ IONIC.api.imagearchive.TableResultsHandler.prototype.getAssociatedIATool = function () { return this._iaTool; }; /** * Set the {@link IONIC.imagearchive.ImageArchiveTool} that is associated to this instance. * It can be used to fetch information related to the displayed results, such as metadata. * * @param {IONIC.imagearchive.ImageArchiveTool} iaTool The tool used to access remote data. * @private */ IONIC.api.imagearchive.TableResultsHandler.prototype.setAssociatedIATool = function (iaTool) { this._iaTool = iaTool; }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. */ /** * @constructor * * @class * * A {@link IONIC.api.imagearchive.ImageArchiveSearchPanel} holds an * HTML element with the necessary editors for the different search * criteria provided by an image archive server. * * @extends IONIC.imagearchive.AbstractImageArchivePanel * * @param {HTMLElement} htmlElt The containing HTML element, or it's * ID. * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the image archive server * @param {HTMLWindow} win (Optional) The window in which is the * document holding the element named "htmlElt", if "htmlElt" is * a string (defaults to the current window). */ IONIC.api.imagearchive.ImageArchiveSearchPanel = function (htmlElt, serverRef, win) { IONIC.imagearchive.AbstractImageArchivePanel.call (this, htmlElt, serverRef, win); var dh = this.getDomHelper (); this._cpnt = dh.elt ("div"); dh.append (htmlElt, this._cpnt); this.buildComponent (); var self = this; this.withImageArchiveCustomQueryables (function (queryables) { self.addCustomQueryables (queryables); self.updateVisibleFields (); }); }; IONIC.misc.extendType (IONIC.api.imagearchive.ImageArchiveSearchPanel, IONIC.imagearchive.AbstractImageArchivePanel); /** * The name of the editor for the keywords criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_KEYWORDS = "kwds"; /** * The name of the editor for the availability criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_AVAILABILITY = "avail"; /** * The name of the editor for the type criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_TYPE = "type"; /** * The name of the editor for the bounding box criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_BBOX = "bbox"; /** * The name of the editor for the timestamp boundaries criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_TIMESTAMP = "ts"; /** * The name of the editor for the resolution criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_RESOLUTION = "res"; /** * The name of the editor for the quality criterion */ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_QUALITY = "qual"; /** * The prefix of the editors for the custom queryables criteria * *

* Since custom criteria have a name, the full name of the editor is * composed as follow: * IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_CUSTOM + queryable.getName (), * where "queryable" is of type * {@link IONIC.imagearchive.ImageArchiveTool.Queryable}. *

*/ IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_CUSTOM = "$custom_"; /** * Creates a <tr> with both the label and the editor's * component, and registers the editor under the given name * * @param {string} editorName The name of the editor * @param {string} label The label to display * @param {IONIC.ui.AbstractEditor} editor The editor * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.addEditor = function (editorName, label, editor) { var dh = this.getDomHelper (); var tbd = this.getComponent ().getElementsByTagName ("tbody") [0]; dh.append (tbd, dh.elt ("tr", dh.elt ("td", dh.txt (label || "")), dh.elt ("td", editor.getComponent ()))); this.registerEditor (editorName, editor); }; /** * Build the HTML component, without the custom queryables (they are * to be fetched from the server) * *

* This actually installs the "regular" (i.e., not the custom * queryables) search criteria editors into the HTML element. *

* * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.buildComponent = function () { var dh = this.getDomHelper (); var tbd = dh.elt ("tbody"); var tbl = dh.elt ("table", tbd); var alias = IONIC.api.imagearchive.ImageArchiveSearchPanel; dh.append (this.getComponent (), tbl); var thisRef = this; // ----------------- // 1) Fixed criteria // 1.1 keywords this.addEditor (alias.ED_KEYWORDS, "Keywords", IONIC.ui.InputEditor.newInstance (dh)); // 1.2 availability var availStor = dh.elt ("select"); availStor.onchange = function () { thisRef.updateVisibleFields (); } var availEditor = new IONIC.ui.SelectEditor (availStor) availEditor.setOptions (["WCS", "WMS", "WMS-WCS", "WFS"], dh, true); this.addEditor (alias.ED_AVAILABILITY, "Availability", availEditor); // 1.3 type var typeStor = dh.elt ("select"); typeStor.onchange = function () { thisRef.updateVisibleFields (); }; dh.mkOpt (typeStor, "Any"); dh.mkOpt (typeStor, "Granule"); dh.mkOpt (typeStor, "Aggregate"); this.addEditor (alias.ED_TYPE, "Type", new IONIC.ui.SelectEditor (typeStor)); // 1.4 bounding box var boxEditor = IONIC.imagearchive.AbstractImageArchivePanel.buildBoundingBoxEditor (dh, this); this.addEditor (alias.ED_BBOX, "Spatial extent", boxEditor); // 1.5 timestamp boundaries var timestampComponent = IONIC.ui.TimestampIntervalEditor.buildComponent (dh); timestampComponent.startCalendar.setYearSelectStartOffset(4); timestampComponent.endCalendar.setYearSelectStartOffset(4); this.addEditor (alias.ED_TIMESTAMP, "Timestamp", new IONIC.ui.TimestampIntervalEditor (timestampComponent)); // 1.6 resolution this.addEditor (alias.ED_RESOLUTION, "Min. image size", IONIC.ui.InputEditor.newInstance (dh)); // 1.7 quality var qualityEditor = new IONIC.ui.SelectEditor (dh.elt ("select")); var qualityOptions = []; for (var i = 100; i >= 0; i -= 10) { qualityOptions.push ("" + i); } qualityEditor.setOptions (qualityOptions, dh); this.addEditor (alias.ED_QUALITY, "Quality", qualityEditor); this.updateVisibleFields (); }; /** * Shows/hides search form fields according to current selected options. * * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.updateVisibleFields = function () { var availableEditor = this.getEditor (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_AVAILABILITY); var typeEditor = this.getEditor (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_TYPE); var resolutionEditor = this.getEditor (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_RESOLUTION); var qualityEditor = this.getEditor (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_QUALITY); var availableOption = availableEditor.getValue(); var typeOption = typeEditor.getValue(); // Given an editor, returns the HTML element containing the editor label and the editor itself function getEditorRow (e) { return e.getComponent ().parentNode.parentNode; } function showElt (elt) { elt.style.display = ""; } function hideElt (elt) { elt.style.display = "none"; } var customRows = []; this.forEachEditor (function (editor, name) { if (name.indexOf (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_CUSTOM) >= 0) { customRows.push (getEditorRow (editor)); } }); var typeRow = getEditorRow (typeEditor); var resolutionRow = getEditorRow (resolutionEditor); var qualityRow = getEditorRow (qualityEditor); var allElements = [typeRow, resolutionRow, qualityRow]; allElements = allElements.concat (customRows); var elementsToHide = []; if (availableOption == "WFS") { elementsToHide.push (typeRow); elementsToHide.push (resolutionRow); elementsToHide.push (qualityRow); elementsToHide = elementsToHide.concat (customRows); } else { if (typeOption != "Granule") { elementsToHide.push (resolutionRow); elementsToHide.push (qualityRow); } } IONIC.misc.forEach (showElt, allElements); IONIC.misc.forEach (hideElt, elementsToHide); }; /** * Adds editors for the custom queryables, that were fetched from the * server. * *

* This actually installs the "regular" (i.e., not the custom * queryables) search criteria editors into the HTML element. *

* * @param {IONIC.imagearchive.ImageArchiveTool.Queryable[]} * customQueryables A list of custom queryables. * * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.addCustomQueryables = function (customQueryables) { var dh = this.getDomHelper (); var alias = IONIC.api.imagearchive.ImageArchiveSearchPanel; var self = this; IONIC.misc.forEach (function (queryable) { var editor, ev, stor; switch (queryable.getType ().toLowerCase ()) { case IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_DATE: editor = IONIC.imagearchive.editors.CustomQueryableDateEditor.newInstance (dh); break; case IONIC.imagearchive.ImageArchiveTool.Queryable.TYPE_INT: editor = IONIC.imagearchive.editors.CustomQueryableIntEditor.newInstance (dh); break; default: ev = queryable.getEnumValues (); if (ev) { editor = IONIC.imagearchive.editors.CustomQueryableSelectEditor.newInstance (dh); editor.setOptions (ev, dh, true); } else { editor = IONIC.imagearchive.editors.CustomQueryableInputEditor.newInstance (dh); } break; } self.addEditor (alias.ED_CUSTOM + queryable.getName (), queryable.getTitle (), editor); }, customQueryables); }; /** * Resets the search panel (clears all editors) */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.reset = function () { IONIC.misc.unimp ("IONIC.api.imagearchive.ImageArchiveSearchPanel", "reset"); }; /** * Get the HTML component * * @return {HTMLDivElement} the HTML component */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.getComponent = function () { return this._cpnt; }; /** * Will call * {@link IONIC.imagearchive.AbstractImageArchivePanel#setAssociatedMap}, * and then will register itself as a listener to that map, so that it * captures it's current extent in order to use it when querying the * server. * * @param {IONIC.api.maps.Map} map The map to be associated to this * instance. * @see IONIC.imagearchive.AbstractImageArchivePanel#setAssociatedMap */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.setAssociatedMap = function (map) { IONIC.imagearchive.AbstractImageArchivePanel.prototype.setAssociatedMap.call (this, map); var self = this; map.onSelectedBoxChanged.subscribe (function (type, args) { var box = args [0]; if (box) { self.getEditor (IONIC.api.imagearchive.ImageArchiveSearchPanel.ED_BBOX).setValue (box); } }); }; /** * Perform the query * *

* See the description of the parameters in the * {@link IONIC.imagearchive.ImageArchiveTool#executeSearch} * function. *

* * @see IONIC.imagearchive.ImageArchiveTool#executeSearch * @see #performSearchWithHandler */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.performSearch = function (beginCallback, iterationCallback, endCallback) { var alias = IONIC.api.imagearchive.ImageArchiveSearchPanel; // Collect parameters... var keywords = this.getEditor (alias.ED_KEYWORDS).getValue (); var resultsType = this.getEditor (alias.ED_TYPE).getValue (); var resultsAvailability = this.getEditor (alias.ED_AVAILABILITY).getValue (); var spatialBounds = this.getEditor (alias.ED_BBOX).getValue (); var temporalBounds = this.getEditor (alias.ED_TIMESTAMP).getValue (); var minimumQuality = this.getEditor (alias.ED_QUALITY).getValue (); var minimumResolution = this.getEditor (alias.ED_RESOLUTION).getValue (); var customQueryables = []; var self = this; this.forEachEditor (function (ed, registeredName) { var val, op, type, name; if (registeredName.indexOf (alias.ED_CUSTOM) >= 0) { name = registeredName.substring (alias.ED_CUSTOM.length); val = ed.getValue (); // we know the editor is of type // IONIC.imagearchive.editors.* op = ed.getOperator (); if (val) { self.withImageArchiveCustomQueryable (name, function (queryable) { var type = queryable.getType (); customQueryables.push ({ name : name, operator : op, value : val, type : type}); }); } } }); var resultsCount = -1; if (resultsAvailability !== "WFS") { if (this.validateSearchForm(keywords, resultsType, resultsAvailability, resultsCount, spatialBounds, temporalBounds, minimumQuality, minimumResolution, customQueryables, this.getPreferredEpsgId ())) { this.getImageArchiveTool ().executeSearch ( keywords, resultsType, resultsAvailability, resultsCount, spatialBounds, temporalBounds, minimumQuality, minimumResolution, customQueryables, this.getPreferredEpsgId (), beginCallback, iterationCallback, endCallback); } else { // Simulate the behaviour of executeSearch beginCallback (false, {}, "{}"); endCallback (false, {}, "{}"); } } else { if (this.validateSearchFormWfs(keywords, resultsCount, spatialBounds, temporalBounds, this.getPreferredEpsgId ())) { this.getImageArchiveTool ().executeWfsSearch ( keywords, resultsCount, spatialBounds, temporalBounds, this.getPreferredEpsgId (), beginCallback, iterationCallback, endCallback); } else { // Simulate the behaviour of executeSearch beginCallback (false, {}, "{}"); endCallback (false, {}, "{}"); } } }; /** * @ignore */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.validateSearchFormWfs = function(keywords, resultsCount, spatialBounds, temporalBounds, srs) { return this.validateSearchFormCommon (keywords, resultsCount, spatialBounds, temporalBounds); }; /** * @ignore */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.validateSearchForm = function(keywords, resultsType, resultsAvailability, resultsCount, spatialBounds, temporalBounds, minimumQuality, minimumResolution, customQueryables, epsgId) { return this.validateSearchFormCommon (keywords, resultsCount, spatialBounds, temporalBounds); }; /** * @ignore */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.validateSearchFormCommon = function(keywords, resultsCount, spatialBounds, temporalBounds) { function display (msg) { alert("One search field is invalid: " + msg); return false; } if ((!temporalBounds[0] && temporalBounds[1]) || (temporalBounds[0] && !temporalBounds[1])) display ("Wrong temporal bounds. Please input exactly 0 or 2 values."); else if (spatialBounds === null) display ("Invalid spatial extent."); else if (Date.parse(temporalBounds[0]) > Date.parse(temporalBounds[1])) display ("First date must be before second date."); else return true; }; /** * Perform the query, but with a dedicated results handler. * * @param {IONIC.misc.AbstractResultsHandler} handler A * results handler that will be in charge of handling the results. */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.performSearchWithHandler = function (handler) { handler.onB4RequestSubmitted (); // Search this.performSearch ( function (success, obj, rt, req) { handler.onBegin (success, obj, rt, req); }, function (node, parent, pos, cnt, depth, req) { handler.onIterate (node, parent, pos, cnt, depth, req); }, function (success, obj, req) { handler.onEnd (success, obj, req); }); }; /** * Get the custom queryables. * *

* WARNING: You should only use this when you are sure * they have already been discovered. *

* * @return {IONIC.imagearchive.ImageArchiveTool.Queryable[]} an * array of custom queryables, or undefined * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.getImageArchiveCustomQueryables = function () { return this._cq; }; /** * Set the custom queryables. * * @param {IONIC.imagearchive.ImageArchiveTool.Queryable[]} custQuer * An array of custom queryables * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.setImageArchiveCustomQueryables = function (custQuer) { this._cq = custQuer; }; /** * @param {function} callback A function of one argument: An array of * custom queryables * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.withImageArchiveCustomQueryables = function (callback) { var self; if (! this.getImageArchiveCustomQueryables ()) { self = this; this.getImageArchiveTool ().withServerStatus (function (statusObj) { self.setImageArchiveCustomQueryables (statusObj.customQueryables); if (callback) { callback (statusObj.customQueryables); } }); } else { if (callback) { callback (this.getImageArchiveCustomQueryables ()); } } }; /** * @param {string} name The name of the custom queryable * @param {function} callback A function of one argument: the type * @private */ IONIC.api.imagearchive.ImageArchiveSearchPanel.prototype.withImageArchiveCustomQueryable = function (name, callback) { this.withImageArchiveCustomQueryables (function (cq) { var found; var alias = IONIC.api.imagearchive.ImageArchiveSearchPanel; IONIC.misc.forEach (function (quer) { if (quer.getName () === name) { found = quer; } }, cq); if (callback) { callback (found); } }); }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. */ /** * @constructor * * @class * * A {@link IONIC.api.imagearchive.ImageArchiveBrowsePanel} holds two * trees: One of which represents the directory structure of the * ImageArchive server, and the other represents what's inside the * current directory level * * @extends IONIC.imagearchive.AbstractImageArchivePanel * * @param {HTMLElement} treeElt The containing aggregate tree HTML element, or its * ID. * * @param {HTMLElement} resElt The containing results HTML element, or its * ID. * * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the image archive server * * @param {HTMLWindow} win (Optional) The window in which is the * document holding the element named "htmlElt", if "htmlElt" is * a string (defaults to the current window). */ IONIC.api.imagearchive.ImageArchiveBrowsePanel = function (treeElt, resElt, serverRef, win, timeline) { IONIC.imagearchive.AbstractImageArchivePanel.call (this, treeElt, serverRef, win); var dh = this.getDomHelper (); treeElt = dh.get(treeElt); resElt = dh.get(resElt); YAHOO.util.Dom.addClass (treeElt, "aggregateTree"); YAHOO.util.Dom.addClass (resElt, "granulesTree"); this._aggregateDecorator = null; this._granuleDecorator = null; this._tree = new YAHOO.widget.TreeView (treeElt); this._resultsListElt = resElt; this._timeline = timeline; // Set the loader for the nodes var self = this; this._tree.setDynamicLoad (function (node, callback) { self.loadChildren (node, callback); }, 1); // Build the directory tree's top node var root = this._tree.getRoot (); var data = IONIC.api.imagearchive.ImageArchiveBrowsePanel.makeNodeDataForDirectoryNode ( this, {name : "ROOT"}); var unused = new YAHOO.widget.TextNode (data, root, false); this.initHolderWithIAData(unused, data); this._tree.subscribe("labelClick", function(node) { self.loadResultsForNodeObject (node, true); }); this._tree.draw (); }; IONIC.misc.extendType (IONIC.api.imagearchive.ImageArchiveBrowsePanel, IONIC.imagearchive.AbstractImageArchivePanel); /** * Fills the granule list (the list on the right of the aggregate tree). * * @param {object} objectNode The YAHOO TextNode containing the IA object * @private */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.loadResultsForNodeObject = function (objectNode, clearTimeline) { var self = this; this.clearResultsList (); var callback = function (iaObject) { var childrenInfos = iaObject.getChildrenInfos (); var resultsList = self.getResultsListElt (); var dh = self.getDomHelper (); var htmlElements = []; self.clearResultsList (); if (self._timeline && clearTimeline) self._timeline.clear(); if (childrenInfos) { IONIC.misc.forEach (function (child) { var data, href, textNode; var typeI = IONIC.api.imagearchive.IAObject.typeStringToType(child.type); // Granule -> Display to the right tree var childIAObject = IONIC.api.imagearchive.IAObject.fromTransportFormat(iaObject.getServerRef(), child); if (typeI === IONIC.api.imagearchive.IAObject.TYPE_GRANULE && (child.availabilityWMS || child.availabilityWCS)) { var elt = dh.elt ("a"); elt.href = "#"; // Display details when elt.onclick = function () { SearchModule.getDetailPanel ().renderDetailsByName (child.name); }; elt.iaObjectName = child.name; // TODO check if this is still necessary dh.append (elt, dh.txt (child.name)); dh.append (resultsList, elt, dh.elt ("br")); self.initHolderWithIAObject(elt, childIAObject, false); child.objectHolder = elt; self.addPopup (elt, elt); htmlElements.push (elt); if (self._timeline) self._timeline.addIAObject(elt); } else if (child.objectHolder && self._timeline) { self._timeline.addIAObject(child.objectHolder); } }, childrenInfos); if (self._timeline) self._timeline.recenter(); if (htmlElements.length > 0 && self._granuleDecorator) { self._granuleDecorator.addElements (htmlElements); } } if (self._timeline) self._timeline.repaintObjects(); }; objectNode.getIAObject(callback, true); }; /** * Get the directory tree * * @return {YAHOO.widget.TreeView} the directory tree */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.getDirectoryTree = function () { return this._tree; }; /** * Get the results (flat) tree * * @return {YAHOO.widget.TreeView} the results flat tree */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.getResultsListElt = function () { return this._resultsListElt; }; /** * Delete all the nodes of the results tree * @private */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.clearResultsList = function () { if (this._granuleDecorator) { this._granuleDecorator.deleteElements (null); } var dh = this.getDomHelper (); var self = this; var resultsDiv = this.getResultsListElt (); IONIC.misc.forEach (function (elt) { self.deletePopup (elt); }, resultsDiv.getElementsByTagName("a")); this.getDomHelper ().clr (resultsDiv); }; /** * An additional 'onhover' event timeout that slows the creation of popups down. * @ignore */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.POPUPTIMEOUT = 500; IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.initHolderWithIAData = function (holder, data) { if (holder) { holder.data = data var self = this; holder.getPopup = function () { if (holder.popupElt) { return holder.popupElt; } else { holder.popupElt = new IONIC.api.imagearchive.IAObjectPopup (self.getDomHelper (), null, self.getAssociatedMap ()); holder.isPopupHidden = true; return holder.popupElt; } } holder.createMoveOverHandler = function () { var mouseoverHandler = function (evt) { holder.getIAObject(function (iaObj) { if (!holder.isPopupHidden) { holder.getPopup ().setContent(iaObj); holder.getPopup ().show(); } }, true); }; return function (evt) { holder.isPopupHidden = false; setTimeout (function () { if (!holder.isPopupHidden) { mouseoverHandler (evt); } }, IONIC.api.imagearchive.ImageArchiveBrowsePanel.POPUPTIMEOUT); } }; holder.createMoveOutHandler = function () { return function (evt) { holder.getPopup().hide(); holder.isPopupHidden = true; }; }; holder.removePopup = function () { if (holder.popupElt) { holder.popupElt.destroy (); holder.popupElt = null; } } /** * Caching/LazyLoading method for the IAObject. * This method relies on a holder object, that must initially at least contain a 'data' attribute * with the uuid and/or the object name. * After the first call to this method, the holder object will contain a 'iaObject' attribute * that contains the actual IAObject. Reciprocally, the holder object will contein a 'iaObject' * attribute to the IA object. * @param {object} node the object that holds or will hold the iaObject, as a 'iaObject' attribute * @param {function} callback the callback to execute once the object is retrieved * @param {boolean} full whether to retrieve the full object description or not * @private */ holder.getIAObject = function (callback, full) { var cbArray = this.waitingCallbacks; if (!cbArray) cbArray = this.waitingCallbacks = new Array(); if (this.isLoadingIAObject) { cbArray[cbArray.length] = callback; return; } else if (this.displayedObject && (!full || this.displayedObject.isFull)) { callback(this.displayedObject); } else { cbArray[cbArray.length] = callback; this.isLoadingIAObject = true; var withObjectFunc; // if the UUID is available, use it fore more efficiency if (this.data.uuid) withObjectFunc = self.getImageArchiveTool().withObjectById; else withObjectFunc = self.getImageArchiveTool().withObjectByName; var holderObj = this; withObjectFunc.call (self.getImageArchiveTool(), this.data.uuid || this.data.iasObjectName, self.getPreferredEpsgId (), function(iaObject) { //self.initHolderWithIAObject(holderObj, iaObject, full); holderObj.displayedObject = iaObject; holderObj.displayedObject.isFull = full; holderObj.isLoadingIAObject = false; for (var idx in holderObj.waitingCallbacks) { holderObj.waitingCallbacks[idx](iaObject); } holderObj.waitingCallbacks = new Array(); }, full); } } } } IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.initHolderWithIAObject = function (holder, iaObject, full) { if (holder && iaObject) { holder.displayedObject = iaObject; holder.displayedObject.isFull = full; this.initHolderWithIAData(holder, { uuid:iaObject.getId(), iasObjectName:iaObject.getName(), title:iaObject.getId()}); } } /** * Function that will be called when a node of the tree * has to be expanded. * * @param {IONIC.api.imagearchive.ImageArchiveBrowsePanel} browsePanel * An instance of browse panel * @param {YAHOO.widget.Node} node The current node of the tree that * must be expanded * @param {function} callback A function of 0 arguments to be called * when the loading is done */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.loadChildren = function (node, callback) { var self = this; var iasTool = new IONIC.imagearchive.ImageArchiveTool (); node.getIAObject( function (iaObject) { // Create new nodes var childrenInfos = iaObject.getChildrenInfos (); var textNodes = []; var displayGranuleTree = false; if (childrenInfos) { IONIC.misc.forEach (function (child) { var data, href, textNode; if (IONIC.api.imagearchive.IAObject.typeStringToType (child.type) === IONIC.api.imagearchive.IAObject.TYPE_AGGREGATE) { data = { label: child.name, iasObjectName : child.name, uuid : child.uuid}; textNode = new YAHOO.widget.TextNode (data, node, false); self.initHolderWithIAData(textNode, data); child.objectHolder = textNode; textNodes.push (textNode); } else { // Children are granule, so we display granule list displayGranuleTree = true; } }, childrenInfos); if (displayGranuleTree) { self.loadResultsForNodeObject (node); } if (callback) { callback (); var htmlElements = []; IONIC.misc.forEach (function (n) { self.addPopup (n.getLabelEl (), n); n.getLabelEl ().iaObjectName = n.data.iasObjectName; // TODO check if this is still necessary htmlElements.push (n.getLabelEl ()); }, textNodes); // Add contextual menu if (htmlElements.length > 0 && self._aggregateDecorator) { self._aggregateDecorator.addElements (htmlElements); } } } }, true); }; /** * @param {object} child An object with at least the * properties: name * @private */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.makeNodeDataForDirectoryNode = function (browsePanel, child) { return {label : child.name, iasObjectName : child.name, uuid : child.uuid}; }; /** * Sets an HTML decorator for the aggregate tree elements. * @param {Object} decorator The decorator. * @see {IONIC.api.imagearchive.DefaultTableRowRenderer.setHtmlDecorator} */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.setAggregateHtmlDecorator = function (decorator) { this._aggregateDecorator = decorator; if (this._timeline) { this._timeline.aggregateDecorator = decorator; } }; /** * Sets an HTML decorator for the granule elements. * @param {Object} decorator The decorator. * @see {IONIC.api.imagearchive.DefaultTableRowRenderer.setHtmlDecorator} */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.setGranuleHtmlDecorator = function (decorator) { this._granuleDecorator = decorator; if (this._timeline) { this._timeline.granuleDecorator = decorator; } }; /** * Asynchronous: gets the iaobject, then set the mouse handlers. * @param {HTMLElement} node The element which will be associated with the popup (will trigger the onmouseover events). * @param {object} objectHolderNode The object that holds the reference to the iaObject. * @private */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.addPopup = function (node, objectHolderNode) { var self = this; node.onmouseover = objectHolderNode.createMoveOverHandler(); node.onmouseout = objectHolderNode.createMoveOutHandler(); node.displayedObjectHolder = objectHolderNode; //node.popupElt = popupElt; }; /** * Deletes the popup associated with an element. * @param {HtmlElement} elt The element which will be associated with the popup (will trigger the onmouseover events). * @private */ IONIC.api.imagearchive.ImageArchiveBrowsePanel.prototype.deletePopup = function (elt) { elt.onmouseover = null; elt.onmouseout = null; if (elt.displayedObjectHolder) { elt.displayedObjectHolder.removePopup(); } }; /** * @constructor * * @class * * A {@link IONIC.api.imagearchive.ImageArchiveDetailPanel} holds a table * representing details about an {@link IONIC.api.imagearchive.IAObject}. * * @extends IONIC.imagearchive.AbstractImageArchivePanel * *

Events

*

*

* * @param {HTMLElement} htmlElt The containing HTML element, or it's * ID. * * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the image archive server * * @param {HTMLWindow} win (Optional) The window in which is the * document holding the element named "htmlElt", if "htmlElt" is * a string (defaults to the current window). */ IONIC.api.imagearchive.ImageArchiveDetailPanel = function (htmlElt, serverRef, win) { IONIC.imagearchive.AbstractImageArchivePanel.call (this, htmlElt, serverRef, win); IONIC.misc.createCustomEvents (["onRendered"], this); }; IONIC.misc.extendType (IONIC.api.imagearchive.ImageArchiveDetailPanel, IONIC.imagearchive.AbstractImageArchivePanel); /** * Renders the details of an {@link IONIC.api.imagearchive.IAObject}. Any previously renderered * detail will be cleared. * * @param {IONIC.api.imagearchive.IAObject} iaObject The iaObject to render. */ IONIC.api.imagearchive.ImageArchiveDetailPanel.prototype.render = function (iaObject) { var dh = this.getDomHelper (); var elt = this.getElement (); var pairs = iaObject.getKeyValuePairs (); var tbody = dh.elt("tbody"); dh.clr (elt); for (var i = 0; i < pairs.length; i++) { var pair = pairs[i]; var tagName = (i === 0) ? "th" : "td"; var row = dh.elt("tr" + ((i%2 == 0) ? ".evenRow" : ".oddRow"), dh.elt (tagName + ".keyCell", dh.txt (pair.key)), dh.elt (tagName + ".valueCell", dh.txt (pair.value))); dh.append (tbody, row); } dh.append (elt, dh.elt("table.detailsPanel", tbody)); this.onRendered.fire (iaObject); }; /** * Renders the details of an {@link IONIC.api.imagearchive.IAObject} given its name. Any previously * renderered detail will be cleared. * * @param {string} name The name of the iaObject to render. */ IONIC.api.imagearchive.ImageArchiveDetailPanel.prototype.renderDetailsByName = function (name) { var self = this; this._displayLoadingImage (); this.getImageArchiveTool ().withCoverageByName ( name, this.getPreferredEpsgId (), function (iaObject) { self.render (iaObject); }, true); }; /** * Renders the details of an {@link IONIC.api.imagearchive.IAObject} given its name. Any previously * renderered detail will be cleared. * * @param {string} name The name of the iaObject to render. */ IONIC.api.imagearchive.ImageArchiveDetailPanel.prototype.renderExtendedDetailsByName = function (name) { var self = this; this._displayLoadingImage (); this.getImageArchiveTool ().withObjectByName ( name, this.getPreferredEpsgId (), function (iaObject) { self.render (iaObject); }, true); }; /** * Display "loading..." icon. * @ignore */ IONIC.api.imagearchive.ImageArchiveDetailPanel.prototype._displayLoadingImage = function () { var elt = this.getElement (); var dh = this.getDomHelper (); var loadingImg = dh.elt("img"); loadingImg.src = IONIC.misc.getWebappBaseUrl () + "/css/third-party/yui-assets/yui/build/tabview/assets/loading.gif"; dh.clr (elt); dh.append(elt, loadingImg); }; /* * Copyright 2005- by IONIC Software S.A., * 18 Av Wallonie, 4460 Grace-Hollogne, Belgium. * All rights reserved. * * This software is the confidential and proprietary information * of IONIC Software S.A.("Confidential Information"). * You shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with IONIC Software. */ /** * @constructor * * @class * * A {@link IONIC.api.imagearchive.ImageArchiveGetCoveragePanel} * allows retrieval of data from a coverage, according to the * description of that coverage provided by the ImageArchive server. * * @extends IONIC.imagearchive.AbstractImageArchivePanel * *

* To an instance of this type, can be attached a * {@link IONIC.api.maps.Map}. If this is the case, the map will be * used for two things: *

    *
  1. * To display a WMS-like view of the coverage, allowing the * user to select the area (bounding box) of the data to * retrieve. *
  2. *
  3. * To get the bounding box for the data to retrieve. *
  4. *
*

*

Events

*

*

*

* * * @param {HTMLElement} htmlElt The containing HTML element, or it's * ID. * * @param {IONIC.api.imagearchive.ServerRef} serverRef A reference to * the image archive server * * @param {string} serverWmsUrl The URL at which the ImageArchive * server can be reached as a WMS. This is useful to display the * current coverage in the associated map (if any) * * @param {HTMLWindow} win (Optional) The window in which is the * document holding the element named "htmlElt", if "htmlElt" is * a string (defaults to the current window). */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel = function (htmlElt, serverRef, serverWmsUrl, win) { IONIC.imagearchive.AbstractImageArchivePanel.call (this, htmlElt, serverRef, win); var dh = this.getDomHelper (); this._cpnt = dh.elt ("div"); this._serverWmsUrl = serverWmsUrl; dh.append (htmlElt, this._cpnt); IONIC.misc.createCustomEvents (["onCoverageDescriptionLoaded", "onCoverageAdded"], this); }; IONIC.misc.extendType (IONIC.api.imagearchive.ImageArchiveGetCoveragePanel, IONIC.imagearchive.AbstractImageArchivePanel); /** * Loads the description of a coverage, and builds/changes the panel * accordingly to that description * * @param {string} name The name of the ImageArchive object * @see #loadCoverageDescription */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.loadCoverageDescriptionByName = function (name) { var self = this; this.getImageArchiveTool ().withCoverageByName ( name, 4326, // this.getPreferredEpsgId (), // FIXME: So far we will // always request the coverage in 4326. The // ideal solution would be to request the object // once to know what GetCoverage-request EPSG // IDs are supported, and then select the first // one from that list, or 4326 if it is present // in the list. This is thus a shortcut that // should work in most cases, but it is // definitely not bullet proof. Nor elegant. // --ad 070904 function (iaObject) { self.loadCoverageDescription (iaObject); }, true); }; /** * Loads the description of a coverage, and builds/changes the panel * accordingly to that description * * @param {IONIC.api.imagearchive.IAObject} iaObject The ImageArchive * object * @see #loadCoverageDescriptionByName */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.loadCoverageDescription = function (iaObject) { this.onCoverageAdded.fire (iaObject.getName ()); this.buildForm (iaObject); var dh = this.getDomHelper (); var ld, map = this.getAssociatedMap (); if (map) { map.removeAllMapLayerDescriptors (); if (iaObject.isAvailableAsWMS ()) { dh.get ("getCoverageLeftPanel").style.display = ""; ld = new IONIC.api.maps.LayerDescriptor ( this.getServerWMSUrl (), [new IONIC.api.maps.WMSSSLayer (iaObject.getName ())], "WMS"); map.setBox (iaObject.getSpatialExtent ().getEnvelope (), false); map.addLayerDescriptor (ld); } else { dh.get ("getCoverageLeftPanel").style.display = "none"; } } this.onCoverageDescriptionLoaded.fire (iaObject); }; /** * Return the URL at which the ImageArchive server can be reached as a * WMS. * * @return {string} the url */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.getServerWMSUrl = function () { return this._serverWmsUrl; }; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.MEASURE_METHOD_PIXEL = 1; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.MEASURE_METHOD_RESOLUTION = 2; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_BBOX = "bbox"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_OUT_SRSES = "outSRSes"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_MEASURE_METHOD = "measureMethod"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_COVERAGE_TYPE = "coverageType"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_CHANNEL = "channel"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_MEASURE_X = "measureX"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_MEASURE_Y = "measureY"; /** * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.getComponent = function () { return this._cpnt; }; /** * Creates a <tr> with both the label and the editor's * component, and registers the editor under the given name * * @param {string} editorName The name of the editor * @param label The label to display: A string or an HTMLElement * @param {IONIC.ui.AbstractEditor} editor The editor * @private */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.addEditor = function (editorName, label, editor) { var dh = this.getDomHelper (); var tbd = this.getComponent ().getElementsByTagName ("tbody") [0]; var labelHolder = (typeof label === "string" ? (dh.txt (label || "")) : label); dh.append (tbd, dh.elt ("tr", dh.elt ("td", labelHolder), dh.elt ("td."+editorName+"EditorCell", editor.getComponent ()))); this.registerEditor (editorName, editor); }; /** * Builds a <form>, which will be used for retrieving the * coverage. * * @param {IONIC.api.imagearchive.IAObject} iaObj The ImageArchive * object. */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.buildForm = function (iaObj) { var dh = this.getDomHelper (); dh.clr (this.getComponent ()); var form = dh.elt ("form", dh.elt ("table.getCoverageForm", dh.elt ("tbody"))); dh.append (this.getComponent (), form); var alias = IONIC.api.imagearchive.ImageArchiveGetCoveragePanel; var boxEditor = IONIC.ui.InputEditor.newInstance (dh); boxEditor.getComponent ().name = "spatialBounds"; this.addEditor (alias.ED_BBOX, "Envelope", boxEditor); var outSrsStor = dh.elt ("select"); outSrsStor.name = "outputEpsgId"; var outSrsEditor = new IONIC.ui.SelectEditor (outSrsStor); var outSrsesOptions = []; // Give WKT SRSes a reasonable size IONIC.misc.forEach (function (srs) { var label = (typeof srs === "number" || srs.length <= 10) ? srs : srs.substring (0, 8); outSrsesOptions.push ({ "label" : label, value: srs }); }, iaObj.getGetCoverageResponseSRSes ()); outSrsEditor.setOptions (outSrsesOptions, dh, true); this.addEditor (alias.ED_OUT_SRSES, "Output SRS", outSrsEditor); var measureMethodStor = dh.elt ("select"); var measureMethodEditor = new IONIC.ui.SelectEditor (measureMethodStor); measureMethodEditor.setOptions ( [{label : "Pixel", value : alias.MEASURE_METHOD_PIXEL}, {label : "Resolution", value : alias.MEASURE_METHOD_RESOLUTION}], dh, true); measureMethodStor.options.selectedIndex = 0; measureMethodStor.onchange = function () { setMeasureType (+ measureMethodStor.options [measureMethodStor.options.selectedIndex].value); }; this.addEditor (alias.ED_MEASURE_METHOD, "Measurement method", measureMethodEditor); var measureXLabelHolder = dh.elt ("span", dh.txt ("X")); var measureXEditor = IONIC.ui.InputEditor.newInstance (dh); this.addEditor (alias.ED_MEASURE_X, measureXLabelHolder, measureXEditor); var measureYLabelHolder = dh.elt ("span", dh.txt ("Y")); var measureYEditor = IONIC.ui.InputEditor.newInstance (dh); this.addEditor (alias.ED_MEASURE_Y, measureYLabelHolder, measureYEditor); var setMeasureType = function (type) { switch (type) { case IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.MEASURE_METHOD_PIXEL: measureXEditor.getComponent ().name = "width"; measureYEditor.getComponent ().name = "height"; measureXEditor.setValue (500); measureYEditor.setValue (500); measureXLabelHolder.innerHTML = "Image width (px)"; measureYLabelHolder.innerHTML = "Image height (px)"; break; case IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.MEASURE_METHOD_RESOLUTION: measureXEditor.getComponent ().name = "resolutionX"; measureYEditor.getComponent ().name = "resolutionY"; measureXEditor.setValue (0.5); measureYEditor.setValue (0.5); measureXLabelHolder.innerHTML = "Resolution (X axis)"; measureYLabelHolder.innerHTML = "Resolution (Y axis)"; break; } }; setMeasureType (alias.MEASURE_METHOD_PIXEL); var outputFormatStor = dh.elt ("select"); outputFormatStor.name = "format"; var outputFormatEditor = new IONIC.ui.SelectEditor (outputFormatStor); outputFormatEditor.setOptions (iaObj.getCoverageTypes (), dh, true); this.addEditor (alias.ED_COVERAGE_TYPE, "Coverage type", outputFormatEditor); var interpStor = dh.elt ("select"); interpStor.name = "interpolationMethod"; var interpEditor = new IONIC.ui.SelectEditor (interpStor); interpEditor.setOptions (iaObj.getInterpolationMethods (), dh, true); this.addEditor (alias.ED_INTERPOLATION_TYPE, "Type of interpolation", interpEditor); if (iaObj.getAxisSet () && iaObj.getAxisSet ().getChannelAxe ()) { var channelAxisNameInput = dh.elt ("input"); channelAxisNameInput.type = "hidden"; channelAxisNameInput.name = "channelAxisName"; channelAxisNameInput.value = iaObj.getAxisSet ().getChannelAxe ().getName (); dh.append (form, channelAxisNameInput); var channelEditor = IONIC.imagearchive.editors.GetCoverageChannelEditor.newInstance (dh, iaObj); this.addEditor (alias.ED_CHANNEL, "Channels", channelEditor); var channelsInput = dh.elt ("input"); channelsInput.type = "hidden"; channelsInput.name = "channels"; dh.append (form, channelsInput); } var submit = dh.elt ("input"); submit.type = "submit"; submit.id = "GetCovergageSubmitButton"; submit.value = "Download coverage"; var tbd = form.getElementsByTagName ("tbody") [0]; dh.append (tbd, dh.elt ("tr", dh.elt ("td", dh.txt ("")), dh.elt ("td", submit))); var url = "/iaGetCoverage.do" + "?objectName=" + escape (iaObj.getName ()) + "&serverRef=" + escape (JSON.stringify (this.getServerRef ().toTransportFormat ())); var self = this; form.onsubmit = function () { // We set the selected channels before sending the form if (channelEditor) { channelsInput.value = channelEditor.getValues (); } // We add the input SRS if none has been specified in the bounding box var boxString = self.getEditor (alias.ED_BBOX).getValue (); if (boxString && boxString.split(",").length === 4) { self.getEditor (alias.ED_BBOX).setValue (boxString + "," + self.getPreferredEpsgId ()); } var box; // By default, use coverage box if (!boxString) { box = iaObj.getSpatialExtent (); if (!box) { alert ("This coverage has no associated bounding box; cannot get coverage."); return false; } self.getEditor (alias.ED_BBOX).setValue (box.getEnvelope ().commaRepresentation ()); } }; IONIC.misc.ajaxifyForm (dh, form, url, true); }; /** * Will call * {@link IONIC.imagearchive.AbstractImageArchivePanel#setAssociatedMap}, * and then will register itself as a listener to that map, so that it * captures the extent of the selected box in order to use it when * querying the server. * * @param {IONIC.api.maps.Map} map The map to be associated to this * instance. * @see IONIC.imagearchive.AbstractImageArchivePanel#setAssociatedMap */ IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.prototype.setAssociatedMap = function (map) { IONIC.imagearchive.AbstractImageArchivePanel.prototype.setAssociatedMap.call (this, map); var self = this; map.onSelectedBoxChanged.subscribe (function (type, args) { var box = args [0]; if (box) { self.getEditor (IONIC.api.imagearchive.ImageArchiveGetCoveragePanel.ED_BBOX). setValue (box.commaRepresentation ()); } }); }; IONIC.defns ("api.imagearchive"); /** * @constructor * * @class * A {@link IONIC.api.imagearchive.TimeLine} holds a timeline UI element able to display coverage objects. * */ IONIC.api.imagearchive.CoverageTimeLine = function (timeline, granuleDecorator, aggregateDecorator) { this.resizeTimerID = null; this.timeline = timeline; this.eventSource = timeline.getBand(0).getEventSource(); this.hasPendingObjects = false; this.granuleDecorator = granuleDecorator; this.aggregateDecorator = aggregateDecorator; } IONIC.api.imagearchive.CoverageTimeLine.prototype.init = function () { } IONIC.api.imagearchive.CoverageTimeLine.prototype.resize = function () { if (this.resizeTimerID == null) { var self = this; this.resizeTimerID = window.setTimeout(function() { self.resizeTimerID = null; self.timeline.layout(); }, 500); } } IONIC.api.imagearchive.CoverageTimeLine.prototype.recenter = function () { if (this.eventSource && this.eventSource.getLatestDate()) { var centerDate = new Date((this.eventSource.getLatestDate().getTime() + this.eventSource.getEarliestDate().getTime())/2); var actualInterval = this.eventSource.getLatestDate().getTime() - this.eventSource.getEarliestDate().getTime(); /* var band0IntervalId = this.snapToTimeInterval(actualInterval/10); var band1IntervalId = this.snapToTimeInterval(actualInterval*3); var band0ActualInterval = actualInterval * 1.2; var band1ActualInterval = Timeline.DateTime.gregorianUnitLengths[Math.min(band1IntervalId+1, Timeline.DateTime.CENTURY)]; */ var band0ActualInterval = actualInterval * 1.2; var band1ActualInterval = actualInterval * 30; var band0IntervalId = this.snapToTimeInterval(actualInterval / 15); var band1IntervalId = this.snapToTimeInterval(band1ActualInterval / 3)-1; if (centerDate) { var band0Ether = new Timeline.LinearEther({ centersOn: centerDate, interval: Timeline.DateTime.gregorianUnitLengths[band0IntervalId], pixelsPerInterval: (this.timeline.getPixelLength()*Timeline.DateTime.gregorianUnitLengths[band0IntervalId])/band0ActualInterval }); var band1Ether = new Timeline.LinearEther({ centersOn: centerDate, interval: Timeline.DateTime.gregorianUnitLengths[band1IntervalId], pixelsPerInterval: (this.timeline.getPixelLength()*Timeline.DateTime.gregorianUnitLengths[band1IntervalId])/band1ActualInterval }); this.timeline.getBand(0)._ether = band0Ether; this.timeline.getBand(0)._etherPainter._unit = band0IntervalId; this.timeline.getBand(1)._ether = band1Ether; this.timeline.getBand(1)._etherPainter._unit = band1IntervalId; band0Ether.initialize(this.timeline); band1Ether.initialize(this.timeline); //this.timeline.getBand(0)._etherPainter.initialize(this.timeline.getBand(0), this.timeline); //this.timeline.getBand(1)._etherPainter.initialize(this.timeline.getBand(1), this.timeline); this.timeline.layout(); //this.timeline.getBand(0).scrollToCenter(centerDate); } } } IONIC.api.imagearchive.CoverageTimeLine.prototype.snapToTimeInterval = function(intervalInMillis) { for (var i=0;i0) { var parseDateTimeFunction = this.eventSource._events.getUnit().getParser("iso8601"); var description = ""; var evt = new Timeline.DefaultEventSource.Event( parseDateTimeFunction(iaObject.getTemporalExtent()[0]), parseDateTimeFunction(iaObject.getTemporalExtent()[1]), null, null, false, iaObject.getName(), iaObject.getTitle(), null, null, null, (iaObject.getType() === IONIC.api.imagearchive.IAObject.TYPE_GRANULE)?"#6e90cb":"#f7efbe", "black" ); evt.displayedObjectHolder = iaObjectHolder; evt.getProperty = function(name) { return this.displayedObjectHolder.displayedObject.getAttribute(name); }; //evt.setWikiInfo(wikiURL, wikiSection); return evt; } else return null; } IONIC.api.imagearchive.CoverageTimeLine.prototype.customizePainter = function(painter) { var selfTimeline = this; painter._onClickDurationEvent = function(domEvt, evt, target) { domEvt.cancelBubble = true; if ("pageX" in domEvt) { var x = domEvt.pageX; var y = domEvt.pageY; } else { var c = Timeline.DOM.getPageCoordinates(target); var x = domEvt.offsetX + c.left; var y = domEvt.offsetY + c.top; } this._showBubble(x, y, evt); }; painter._onClickInstantEvent = function(domEvt, evt, target) { domEvt.cancelBubble = true; if ("pageX" in domEvt) { var x = domEvt.pageX; var y = domEvt.pageY; } else { var c = Timeline.DOM.getPageCoordinates(target); var x = domEvt.offsetX + c.left; var y = domEvt.offsetY + c.top; } this._showBubble(x, y, evt); }; painter.paint = function() { var eventSource = this._band.getEventSource(); if (eventSource == null) { return; } if (this._highlightLayer != null) { this._band.removeLayerDiv(this._highlightLayer); } this._highlightLayer = this._band.createLayerDiv(105); this._highlightLayer.setAttribute("name", "event-highlights"); this._highlightLayer.style.display = "none"; if (this._eventLayer != null) { this._band.removeLayerDiv(this._eventLayer); } this._eventLayer = this._band.createLayerDiv(110); this._eventLayer.setAttribute("name", "events"); this._eventLayer.style.display = "none"; var minDate = this._band.getMinDate(); var maxDate = this._band.getMaxDate(); var doc = this._timeline.getDocument(); var p = this; var eventLayer = this._eventLayer; var highlightLayer = this._highlightLayer; var showText = this._showText; var theme = this._params.theme; var eventTheme = theme.event; var trackOffset = eventTheme.track.offset; var trackHeight = ("trackHeight" in this._params) ? this._params.trackHeight : eventTheme.track.height; var trackGap = ("trackGap" in this._params) ? this._params.trackGap : eventTheme.track.gap; //if (this._timeline.isHorizontal()) { var appendIcon = function(evt, div) { var icon = evt.getIcon(); var img = Timeline.Graphics.createTranslucentImage( doc, icon != null ? icon : eventTheme.instant.icon ); div.appendChild(img); div.style.cursor = "pointer"; Timeline.DOM.registerEvent(div, "mousedown", function(elmt, domEvt, target) { p._onClickInstantEvent(img, domEvt, evt); }); }; var createHighlightDiv = function(highlightIndex, startPixel, length, highlightOffset, highlightWidth) { if (highlightIndex >= 0) { var color = eventTheme.highlightColors[Math.min(highlightIndex, eventTheme.highlightColors.length - 1)]; var div = doc.createElement("div"); div.style.position = "absolute"; div.style.overflow = "hidden"; div.style.left = (startPixel - 3) + "px"; div.style.width = (length + 6) + "px"; div.style.top = highlightOffset + "em"; div.style.height = highlightWidth + "em"; div.style.background = color; //Timeline.Graphics.setOpacity(div, 50); highlightLayer.appendChild(div); } }; var createInstantDiv = function(evt, startPixel, endPixel, streamOffset, highlightIndex, highlightOffset, highlightWidth) { if (evt.isImprecise()) { // imprecise time var length = Math.max(endPixel - startPixel, 1); var divImprecise = doc.createElement("div"); divImprecise.style.position = "absolute"; divImprecise.style.overflow = "hidden"; divImprecise.style.top = streamOffset; divImprecise.style.height = trackHeight + "em"; divImprecise.style.left = startPixel + "px"; divImprecise.style.width = length + "px"; divImprecise.style.background = eventTheme.instant.impreciseColor; if (eventTheme.instant.impreciseOpacity < 100) { Timeline.Graphics.setOpacity(divImprecise, eventTheme.instant.impreciseOpacity); } eventLayer.appendChild(divImprecise); } var div = doc.createElement("div"); div.style.position = "absolute"; div.style.overflow = "hidden"; eventLayer.appendChild(div); var foreground = evt.getTextColor(); var background = evt.getColor(); var realign = -8; // shift left so that icon is centered on startPixel var length = 16; if (showText) { div.style.width = eventTheme.label.width + "px"; div.style.color = foreground != null ? foreground : eventTheme.label.outsideColor; appendIcon(evt, div); div.appendChild(doc.createTextNode(evt.getText())); } else { if (p._showLineForNoText) { div.style.width = "1px"; div.style.borderLeft = "1px solid " + (background != null ? background : eventTheme.instant.lineColor); realign = 0; // no shift length = 1; } else { appendIcon(evt, div); } } div.style.top = streamOffset; div.style.height = trackHeight + "em"; div.style.left = (startPixel + realign) + "px"; createHighlightDiv(highlightIndex, (startPixel + realign), length, highlightOffset, highlightWidth); }; var createDurationDiv = function(evt, startPixel, endPixel, streamOffset, highlightIndex, highlightOffset, highlightWidth) { var attachClickEvent = function(elmt) { elmt.style.cursor = "pointer"; /* Timeline.DOM.registerEvent(elmt, "mousedown", function(elmt, domEvt, target) { p._onClickDurationEvent(domEvt, evt, target); }); */ elmt.displayedObjectHolder = evt.displayedObjectHolder; if (selfTimeline.aggregateDecorator) selfTimeline.aggregateDecorator.addElements([elmt]); Timeline.DOM.registerEvent(elmt, "mouseover", function(elmt, domEvt, target) { evt.displayedObjectHolder.createMoveOverHandler()(domEvt); }); Timeline.DOM.registerEvent(elmt, "mouseout", function(elmt, domEvt, target) { evt.displayedObjectHolder.createMoveOutHandler()(domEvt); }); }; var length = Math.max(endPixel - startPixel, 1); if (evt.isImprecise()) { // imprecise time var div = doc.createElement("div"); div.style.position = "absolute"; div.style.overflow = "hidden"; div.style.top = streamOffset; div.style.height = trackHeight + "em"; div.style.left = startPixel + "px"; div.style.width = length + "px"; div.style.background = eventTheme.duration.impreciseColor; if (eventTheme.duration.impreciseOpacity < 100) { Timeline.Graphics.setOpacity(div, eventTheme.duration.impreciseOpacity); } eventLayer.appendChild(div); var startDate = evt.getLatestStart(); var endDate = evt.getEarliestEnd(); var startPixel2 = Math.round(p._band.dateToPixelOffset(startDate)); var endPixel2 = Math.round(p._band.dateToPixelOffset(endDate)); } else { var startPixel2 = startPixel; var endPixel2 = endPixel; } var foreground = evt.getTextColor(); var outside = true; if (startPixel2 <= endPixel2) { length = Math.max(endPixel2 - startPixel2, 1); outside = !(length > eventTheme.label.width); div = doc.createElement("div"); div.style.position = "absolute"; div.style.overflow = "hidden"; div.style.top = streamOffset; div.style.height = trackHeight + "em"; div.style.left = startPixel2 + "px"; div.style.width = length + "px"; var background = evt.getColor(); div.style.background = background != null ? background : eventTheme.duration.color; if (eventTheme.duration.opacity < 100) { Timeline.Graphics.setOpacity(div, eventTheme.duration.opacity); } eventLayer.appendChild(div); } else { var temp = startPixel2; startPixel2 = endPixel2; endPixel2 = temp; } if (div == null) { console.log(evt); } attachClickEvent(div); if (showText) { var divLabel = doc.createElement("div"); divLabel.style.position = "absolute"; divLabel.style.top = streamOffset; divLabel.style.height = trackHeight + "em"; divLabel.style.left = ((length > eventTheme.label.width) ? startPixel2 : endPixel2) + "px"; divLabel.style.width = eventTheme.label.width + "px"; divLabel.style.color = foreground != null ? foreground : (outside ? eventTheme.label.outsideColor : eventTheme.label.insideColor); divLabel.style.overflow = "hidden"; divLabel.appendChild(doc.createTextNode(evt.getText())); eventLayer.appendChild(divLabel); attachClickEvent(divLabel); } createHighlightDiv(highlightIndex, startPixel, endPixel - startPixel, highlightOffset, highlightWidth); }; //} var createEventDiv = function(evt, highlightIndex) { var startDate = evt.getStart(); var endDate = evt.getEnd(); var startPixel = Math.round(p._band.dateToPixelOffset(startDate)); var endPixel = Math.round(p._band.dateToPixelOffset(endDate)); var streamOffset = (trackOffset + p._layout.getTrack(evt) * (trackHeight + trackGap)); if (evt.isInstant()) { createInstantDiv(evt, startPixel, endPixel, streamOffset + "em", highlightIndex, streamOffset - trackGap, trackHeight + 2 * trackGap); } else { createDurationDiv(evt, startPixel, endPixel, streamOffset + "em", highlightIndex, streamOffset - trackGap, trackHeight + 2 * trackGap); } }; var filterMatcher = (this._filterMatcher != null) ? this._filterMatcher : function(evt) { return true; }; var highlightMatcher = (this._highlightMatcher != null) ? this._highlightMatcher : function(evt) { return -1; }; var iterator = eventSource.getEventIterator(minDate, maxDate); while (iterator.hasNext()) { var evt = iterator.next(); if (filterMatcher(evt)) { createEventDiv(evt, highlightMatcher(evt)); } } this._highlightLayer.style.display = "block"; this._eventLayer.style.display = "block"; }; }