Project

General

Profile

1
<%@ page language="java"%>
2
<%
3
/**
4
 * 
5
 * '$RCSfile$'
6
 * Copyright: 2008 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    '$Author: leinfelder $'
9
 *      '$Date: 2011-01-04 11:19:17 -0800 (Tue, 04 Jan 2011) $'
10
 * '$Revision: 5762 $'
11
 * 
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 * 
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
     
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */  
26
%>
27

    
28
<%@ include file="../../common/common-settings.jsp"%>
29
<%@ include file="../../common/configure-check.jsp"%>
30

    
31
<html>
32
<head>
33
<title>Semantic search</title>
34
<link rel="stylesheet" type="text/css" href="<%=STYLE_SKINS_URL%>/semtools/semtools.css">
35
<link rel="stylesheet" type="text/css" href="<%=STYLE_COMMON_URL%>/jquery/jqueryui/css/smoothness/jquery-ui-1.8.6.custom.css">
36

    
37
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/jquery/jquery.js"></script>
38
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/jquery/jsTree/_lib/jquery.cookie.js"></script>
39
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/jquery/jsTree/jquery.jstree.js"></script>
40
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/jquery/jqueryui/js/jquery-ui-1.8.6.custom.min.js"></script>
41
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/jquery/busy/jquery.busy.js"></script>
42

    
43
<script language="javascript" type="text/javascript" src="<%=STYLE_SKINS_URL%>/semtools/search.js"></script>
44
<script language="javascript" type="text/javascript" src="<%=STYLE_SKINS_URL%>/semtools/semtools.js"></script>
45
<script language="javascript" type="text/javascript" src="<%=STYLE_COMMON_URL%>/branding.js"></script>
46

    
47
<script language="Javascript" type="text/JavaScript"><!--
48
function populateActiveDomain(divId, class) {
49
	// collect the filtering values we have so far
50
	// these are hidden input fields in the form for holding the selected values
51
	var entity = $("#activeEntitiesValue").val() ? $("#activeEntitiesValue").val() : "";
52
	var characteristic = $("#activeCharacteristicsValue").val() ? $("#activeCharacteristicsValue").val() : "";
53
	var protocol = $("#activeProtocolsValue").val() ? $("#activeProtocolsValue").val() : "";
54
	var measurement = $("#activeMeasurementsValue").val() ? $("#activeMeasurementsValue").val() : "";
55
	
56
	// TODO: remember the selected value for this when filtering by active domain
57
	var selectedNode = $("#" + divId).jstree("get_selected", $("#" + divId));
58
	var selectedNodeId = $(selectedNode).attr("id");
59
	//alert(divId + " selected node: " + selectedNodeId);
60
	
61
	// load the tree for the given div, passing in the other filtered values
62
	$("#" + divId).load(
63
		"<%=SERVLET_URL%>", 
64
		{
65
			'action': "getactivedomain",
66
			'class': class,
67
			'entity': entity,
68
			'characteristic': characteristic,
69
			'protocol': protocol,
70
			'measurement': measurement
71
		},
72
		// call back function when loading finishes
73
		function(response, status, xhr) {
74
			//alert("callback for: " + divId + " selected node: " + selectedNodeId);
75
			// error
76
			if (status == "error") {
77
				var msg = "Sorry but there was an error: ";
78
				$("#error").html(msg + xhr.status + " " + xhr.statusText);
79
			}
80
 
81
			// make it a js tree
82
			$(function () {
83
				$("#" + divId)
84
					//bind calls here
85
					.jstree({
86
						"ui" : {
87
							"select_limit" : 1,
88
							"select_multiple_modifier" : "alt",
89
							"selected_parent_close" : "select_parent"//,
90
							//"initially_select" : [ selectedNodeId ]
91
						},
92
						"themes" : {
93
							"theme" : "default",
94
							"dots" : true,
95
							"icons" : false
96
						},
97
						//"core" : { "initially_open" : [ selectedNodeId ] },
98
						"search" : { "case_insensitive" : true },
99
						//"cookies" : { 
100
						//		"save_opened" : "jstree_open_" + divId,
101
						//		"save_selected" : "jstree_select_" + divId,
102
						//},
103
						"plugins" : [ 
104
							"themes", 
105
							"html_data", 
106
							"ui", 
107
							//"cookies", 
108
							"search" ]
109
					});
110
			});
111

    
112
			// enable searching on it
113
			$("#" + divId + "Search").keyup(
114
				function () {
115
					var searchTerm = $("#" + divId + "Search").val();
116
					if (searchTerm.length >= 3) {
117
						// search
118
						$("#" + divId).jstree("search", searchTerm);
119
						// now prune
120
						prune(divId, "jstree-search");
121
						// is it an exact match?
122
						checkExactMatch(divId, searchTerm, "jstree-search");
123
					}
124
				});
125
			
126
			// toggle the active domain prune
127
			$("#" + divId + "Only").click(function() {
128
				doActiveDomain(divId);
129
			});	
130

    
131
			// actually prune if we should
132
			doActiveDomain(divId);
133

    
134
			// open first node always
135
			$("#" + divId).jstree("open_node", $("#" + divId).children("ul").first().children("li").first());
136
			
137
			// open to the node to last selected
138
			var nodePath = $("#" + divId).jstree("get_path", $(selectedNode));
139
			if (nodePath) {
140
				for (var index = 0; index < nodePath.length; index++) {
141
					$("#" + divId).jstree("open_node", $("#" + nodePath[index]));
142
				}
143
				// select the original node
144
				$("#" + divId).jstree("select_node", $(selectedNode), false);
145
				$("#" + divId).jstree("refresh", $(selectedNode));
146
				// TODO: scroll to selected node. 
147
				// This is supposed to be part of jsTree 1.0-rc2 but appears to be broken
148
			}
149
			
150
		});
151
}
152
/**
153
* Prunes the given tree to inlcude the given matched class 
154
**/
155
function prune(divId, matchClass) {
156

    
157
	// show all nodes (reset)
158
	$("#" + divId).find("li").show();
159
	
160
	// done if we don't have any thing to prune
161
	if (!matchClass) {
162
		return;
163
	}
164
	
165
	// get all non-matched anchor tags
166
	var nonmatches = $("#" + divId).find("a").not("." + matchClass);
167
	
168
	// get their parent nodes
169
	nonmatches = $(nonmatches).parents("li");
170

    
171
	// are there any matches under each parent node?
172
	$(nonmatches).each(
173
		function(index) {
174
			// do any chidren match?
175
			var childMatches = $(this).find("a." + matchClass);
176
			if (childMatches && childMatches.length > 0) {
177
				return true;
178
			}
179
			// parent matches?
180
			var parentMatches = $(this).parents("li").children("a." + matchClass);
181
			if (parentMatches && parentMatches.length > 0) {
182
				return true;
183
			}
184
			// hide this node if no matches under it
185
			$(this).hide();
186
		});
187
}
188
function checkExactMatch(divId, searchTerm, matchClass) {
189
	// get the current search matches
190
	var matches = $("#" + divId).find("a." + matchClass);
191
	// get their parent nodes
192
	matches = $(matches).parents("li");
193
	// check for exact matches
194
	var exactMatch = $(matches).filter("#" + searchTerm).first();
195
	if (exactMatch && exactMatch.length == 1) {
196
		//alert("exactMatch: " + exactMatch);
197
		// select in the tree, honoring the configured selection limit
198
		$("#" + divId).jstree("select_node", $(exactMatch), true);
199
		// act as those you clicked it
200
		// TODO: convert to event listeners on the tree
201
		select($(exactMatch).children("a"));
202
	}
203
}
204
function doActiveDomain(divId) {
205
	if ($("#" + divId + "Only").is(":checked")) {
206
		// prune to active
207
		prune(divId, "bold");
208
	} else {
209
		// reset
210
		prune(divId, null);
211
	}
212
}
213
function initialize(source) {
214
	// we don't want to reload the source of the filtering request
215
	// but we do want to reload the other trees for active domains
216
	// we reload all of them if no source is given - first time the page loads
217
	if (source) {
218
		source = $(source).attr("id");
219
	}
220
	if (!source) {
221
		source = "";
222
	}
223
	if (source != 'activeEntities') {
224
		populateActiveDomain('activeEntities', 'org.ecoinformatics.sms.annotation.Entity');
225
	}
226
	if (source != 'activeCharacteristics') {
227
		populateActiveDomain('activeCharacteristics', 'org.ecoinformatics.sms.annotation.Characteristic');
228
	}
229
	if (source != 'activeProtocols') {
230
		populateActiveDomain('activeProtocols', 'org.ecoinformatics.sms.annotation.Protocol');
231
	}
232
	if (source != 'activeMeasurements') {
233
		populateActiveDomain('activeMeasurements', 'org.ecoinformatics.sms.annotation.Measurement');
234
	}
235
}
236
function select(item) {
237

    
238
	// get the selected value, stored in the title attribute of the item <a> tag
239
	var value = $(item).attr("title");
240
	//alert("value: " + value);
241
	
242
	// get the parent div so we know what kind of class it is meant to filter
243
	// this is "the first parent of the class 'select'"
244
	var parent = $(item).parents("div.select:first");
245
	//alert("parent: " + parent);
246
	
247
	// set the value for the hidden input value
248
	// the input field of class "value" will hold it, this way we don't need to know the id
249
	var input = $(parent).children("input.value");
250
	$(input).val(value);
251
	//alert("input: " + input);
252
	
253
	// set it in the search field
254
	var treeInstance = $(item).parents("div.jstree:first");
255
	var shortName = $(item).parent().attr("id");
256
	$("#" + $(treeInstance).attr("id") + "Search").val(shortName)
257

    
258
	// refresh the search results
259
	doSearch($("#searchForm").get(0));
260
	
261
	// refresh the other trees for active domain after this filtering action
262
	initialize($(parent).children("div"));
263
}
264
function doSearch(formObj) {
265
	// set the hidden parameters based on the current state of the form
266
	checkSearch(formObj);
267
	
268
	// start the busy indicator
269
	$("#searchResults").busy(
270
			{
271
				position	: 'left', 
272
				offset		: -30, 
273
				hide		: true, 
274
				img			: "<%=STYLE_COMMON_URL%>/jquery/busy/busy.gif" 
275
			});
276
	
277
	//load the results
278
	$("#searchResults").load(
279
		"<%=SERVLET_URL%>" + " #content_wrapper",
280
		$(formObj).serialize(),
281
		// call back function when loading finishes
282
		function(response, status, xhr) {
283
			if (status == "error") {
284
				var msg = "Sorry but there was an error performing the search: ";
285
				$("#error").html(msg + xhr.status + " " + xhr.statusText);
286
			}
287
			// collapsible search results - show and hide the next div
288
			$(function() {
289
				$('.accordian').click(function() {
290
					$(this).parent().next().slideToggle("slow");
291
					return false;
292
				}).parent().next().hide();
293
			});
294
			
295
			// stop the busy indicator
296
			$("#searchResults").busy("hide");
297
		});
298
		
299
	return false;
300
	
301
}
302
function clearForm() {
303
	// clear the form values
304
	$('#searchForm').get(0).reset();
305
	// clear each of the tree selections
306
	$(".jstree").each(function(index) {
307
		$(this).jstree("deselect_all");
308
	});
309
	$("input.value").each(function(index) {
310
		$(this).val("");
311
	});
312
	// reload the trees
313
	initialize();
314
	// reload the search results
315
	//alert($('#searchForm').get(0));
316
	doSearch($('#searchForm').get(0));
317
}
318
/**
319
 * Perform this when the page first loads
320
 */
321
function pageLoad() {
322
	initialize();
323
	doSearch($('#searchForm').get(0));
324
}
325
function donothing() {}
326
--></script>
327

    
328
</head>
329
<body onload="pageLoad()">
330
<script language="javascript">
331
	insertTemplateOpening("<%=CONTEXT_URL%>");
332
</script>
333

    
334
<div id="content_wrapper">
335
 
336
<h2>Semantic search</h2>
337

    
338
<div id="error">
339
	<!-- error messages here -->
340
</div>
341

    
342
<!-- set up the tabs -->
343
<script>
344
	$(function() {
345
		$("#searchTabs").tabs();
346
		$("#searchTabs").tabs("add", "#ecpTab", "Entity, Characteristic, Protocol");
347
		$("#searchTabs").tabs("add", "#measurementTab", "Measurement");
348
		$("#searchTabs").tabs("add", "#optionsTab", "Options");
349
	});
350
</script>
351

    
352
<form method="POST" 
353
		action="<%=SERVLET_URL%>" 
354
		target="_top" 
355
		id="searchForm" 
356
		name="searchForm" 
357
		onSubmit="return doSearch(this)">
358
	<input name="query" type="hidden" />
359
	<input name="qformat" value="semtools" type="hidden" />
360
	<input name="includeHeader" value="false" type="hidden" />
361
	<input name="action" value="semquery" type="hidden" />
362

    
363
	<!-- tabs for the search interface -->		
364
	<div id="searchTabs">
365
		<!-- place holder for ui tabs -->
366
		<ul></ul>
367
	
368
		<!-- other criteria tabs -->
369
		<div id="ecpTab">
370
			<table>
371
				<tr>
372
					<td>
373
						<table class="subGroup subGroup_border">
374
							
375
							<tr>
376
								<th><p>Find observations of</p></th>
377
							</tr>
378
							<tr>
379
								<td>
380
									<input type="text" id="activeEntitiesSearch" />
381
									<input type="checkbox" id="activeEntitiesOnly" title="Show only active concepts" />
382
									<div class="select">
383
										<div id="activeEntities" class="activeTree">
384
											<p>loading...</p>
385
										</div>
386
										<input type="hidden" class="value" name="activeEntitiesValue" id="activeEntitiesValue"/>
387
										<input type="hidden" name="activeEntitiesClass" id="activeEntitiesClass" value="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Entity"/>
388
									</div>
389
								</td>
390
							</tr>
391
						</table>
392
					</td>
393
					<td>
394
						<table class="subGroup subGroup_border">
395
							<tr>
396
								<th><p>with measurements of</p></th>
397
							</tr>
398
							<tr>
399
								<td>
400
									<input type="text" id="activeCharacteristicsSearch" />
401
									<input type="checkbox" id="activeCharacteristicsOnly" title="Show only active concepts" />
402
									<div class="select">
403
										<div id="activeCharacteristics" class="activeTree">
404
											<p>loading...</p>
405
										</div>
406
										<input type="hidden" class="value" name="activeCharacteristicsValue" id="activeCharacteristicsValue"/>
407
										<input type="hidden" name="activeCharacteristicsClass" id="activeCharacteristicsClass" value="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Characteristic"/>
408
									</div>
409
								</td>
410
							</tr>
411
						</table>
412
					</td>
413
					<td>
414
						<table class="subGroup subGroup_border">
415
							<tr>
416
								<th><p>using procedures outlined by</p></th>
417
							</tr>
418
							<tr>
419
								<td>
420
									<input type="text" id="activeProtocolsSearch" />
421
									<input type="checkbox" id="activeProtocolsOnly" title="Show only active concepts" />
422
									<div class="select">
423
										<div id="activeProtocols" class="activeTree">
424
											<p>loading...</p>
425
										</div>
426
										<input type="hidden" class="value" name="activeProtocolsValue" id="activeProtocolsValue" />
427
										<input type="hidden" name="activeProtocolsClass" id="activeProtocolsClass" value="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Protocol"/>
428
									</div>
429
								</td>
430
							</tr>
431
						</table>
432
					</td>
433
				</tr>
434
			</table>
435
		</div>
436
		
437
		<!-- measurement -->
438
		<div id="measurementTab">
439
			<table class="subGroup subGroup_border onehundred_percent">
440
				
441
				<tr>
442
					<th><p>a template that defines Entity, Characteristic, Standard, and/or Protocol</p></th>
443
				</tr>
444
				
445
				<tr>
446
					<td>
447
						<input type="text" id="activeMeasurementsSearch" />
448
						Only active? <input type="checkbox" id="activeMeasurementsOnly" title="Show only active concepts"/>
449
						<div class="select">
450
							<div id="activeMeasurements" class="activeTree" style="width: 100%">
451
								<p>loading...</p>
452
							</div>
453
							<input type="hidden" class="value" name="activeMeasurementsValue" id="activeMeasurementsValue"/>
454
							<input type="hidden" name="activeMeasurementsClass" id="activeMeasurementsClass" value="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Measurement"/>
455
						</div>
456
					</td>
457
				</tr>
458
			</table>
459
		</div>
460
		
461
		<!-- query options -->
462
		<div id="optionsTab">
463
			<table class="group group_border">
464
				<tr>
465
					<th colspan="2">
466
						<p>
467
							Locate <b>data packages</b> that have been semantically annotated within the observation model by
468
							selecting concepts from OBOE extension ontologies
469
						</p>
470
					</th>
471
				</tr>
472
				
473
				<tr>
474
					
475
					<td colspan="1">Match All? <input type="checkbox" name="matchAll" checked="checked"/></td>
476
				
477
					<td colspan="1">From same Observation? <input type="checkbox" name="strict"/></td>
478
				</tr>
479
				
480
			</table>
481
		</div>	
482
					
483
	</div>
484
	
485
	<br/>
486
	
487
	<!-- search results here -->	
488
	<table class="subGroup subGroup_border onehundred_percent">
489
		<tr>
490
			<th>
491
				Search Results
492
				<input type="reset" value="Clear" onclick="clearForm()"/>
493
			</th>
494
		</tr>
495
		<tr>
496
			<td>
497
				<div id="searchResults">
498
				No query has been specified	
499
				</div>
500
			</td>
501
		</tr>
502
	</table>	
503

    
504
</form>
505

    
506

    
507

    
508
<!-- Included default search/login -->
509
<% if ( PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) { %>
510
<script language="javascript">
511
	insertMap("<%=CONTEXT_URL%>");
512
</script>
513
<br/>
514
<% } %>
515
  
516
<script language="javascript">
517
	insertSearchBox("<%=CONTEXT_URL%>");
518
	insertLoginBox("<%=CONTEXT_URL%>");	
519
</script>
520

    
521
</div>
522

    
523
<script language="javascript">
524
	insertTemplateClosing("<%=CONTEXT_URL%>");
525
</script>
526

    
527
</body>
528
</html>
(5-5/14)