Changeset 4250
- Timestamp:
- Apr 25, 2008, 3:41:14 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/clients/web/net/sf/basedb/clients/web/taglib/table/ColumnDef.java
r4232 r4250 64 64 enum=... 65 65 enumeration=... 66 smartenum=true|false 66 67 title=... 67 68 sortable=true|false … … 233 234 234 235 <tr> 236 <td>smartenum</td> 237 <td>false (true for annotations)</td> 238 <td>no</td> 239 <td> 240 If the filter for an enumeration column should be displayed as 241 a free text field or a selection list. Default is to use a selection 242 list. Use this option only if both the hidden key and the displayed 243 value of the enumeration is the same. The "smartness" of this options 244 is that as the user types text, the browser will dynamically display a list 245 of options matching the entered text. 246 </td> 247 </tr> 248 249 <tr> 235 250 <td>formatter</td> 236 251 <td>-</td> … … 346 361 private Enumeration<String, String> enumeration; 347 362 363 private boolean smartEnum; 364 348 365 private Formatter<?> formatter; 349 366 … … 507 524 { 508 525 return enumeration; 526 } 527 528 /** 529 @since 2.7 530 */ 531 public void setSmartenum(boolean smartEnum) 532 { 533 this.smartEnum = smartEnum; 509 534 } 510 535 … … 602 627 Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(table.getSc()); 603 628 629 String inputName = "filter:" + valueType.name() + ":" + getFilterproperty(); 604 630 if (getEnumeration() != null) 605 631 { 606 632 String filterValue = filter == null ? "" : Base.getPropertyFilterString(filter, dateFormatter); 607 sb.append("<select name=\"filter:").append(valueType.name()).append(":").append(getFilterproperty()).append("\""); 608 sb.append(" onchange=\"Forms.submit(event);\">\n"); 609 sb.append("<option value=\"\">"); 610 Enumeration<String, String> enumeration = getEnumeration(); 611 for (int i = 0; i < enumeration.size(); ++i) 633 if (smartEnum || isAnnotation) 612 634 { 613 String selected = filterValue.equals(enumeration.getKey(i).trim()) ? " selected" : ""; 614 sb.append("<option value=\"").append(enumeration.getKey(i)).append("\"").append(selected); 615 sb.append(">").append(enumeration.getValue(i)).append("\n"); 635 sb.append("<span class=\"smartinput\"><input class=\"text\" type=\"text\""); 636 sb.append(" name=\"").append(inputName).append("\""); 637 sb.append(" size=\"20\""); 638 sb.append(" maxlength=\"").append(PropertyFilter.MAX_VALUE_LENGTH).append("\""); 639 sb.append(" value=\"").append(filterValue).append("\""); 640 sb.append(">"); 641 sb.append("<img class=\"smartimage\" src=\"").append(table.getPage().getRoot()).append("images/dropdown.png\""); 642 sb.append(" onclick=\"SmartEnum.activateAndDisplay('"); 643 sb.append(table.getId()).append("','").append(inputName).append("')\">"); 644 sb.append("</span>"); 645 StringBuilder addSmart = new StringBuilder(); 646 addSmart.append("SmartEnum.enableForField('").append(table.getId()).append("'"); 647 addSmart.append(",'").append(inputName).append("'"); 648 addSmart.append(",["); 649 for (int i = 0; i < enumeration.size(); ++i) 650 { 651 if (i > 0) addSmart.append(","); 652 addSmart.append("'").append(HTML.javaScriptEncode(enumeration.getKey(i))).append("'"); 653 } 654 addSmart.append("]);\n"); 655 table.addScript(addSmart.toString()); 616 656 } 617 sb.append("</select>"); 657 else 658 { 659 sb.append("<select name=\"").append(inputName).append("\""); 660 sb.append(" onchange=\"Forms.submit(event);\">\n"); 661 sb.append("<option value=\"\">"); 662 Enumeration<String, String> enumeration = getEnumeration(); 663 for (int i = 0; i < enumeration.size(); ++i) 664 { 665 String selected = filterValue.equals(enumeration.getKey(i).trim()) ? " selected" : ""; 666 sb.append("<option value=\"").append(enumeration.getKey(i)).append("\"").append(selected); 667 sb.append(">").append(enumeration.getValue(i)).append("\n"); 668 } 669 sb.append("</select>"); 670 } 618 671 } 619 672 else if (valueType == Type.BOOLEAN) 620 673 { 621 674 boolean filterValue = filter == null ? false : Values.getBoolean(filter.getValue()); 622 String radioName = "filter:"+valueType.name()+":"+getFilterproperty(); 623 sb.append("<input type=\"radio\" name=\"").append(radioName).append("\""); 675 sb.append("<input type=\"radio\" name=\"").append(inputName).append("\""); 624 676 sb.append(filter == null ? "checked" : ""); 625 677 sb.append(" value=\"\" onclick=\"Forms.submit(event)\">").append("any"); 626 678 627 sb.append("<input type=\"radio\" name=\"").append( radioName).append("\"");679 sb.append("<input type=\"radio\" name=\"").append(inputName).append("\""); 628 680 sb.append(filter != null && filterValue ? "checked" : ""); 629 681 sb.append(" value=\"true\" onclick=\"Forms.submit(event)\">").append("true"); 630 682 631 sb.append("<input type=\"radio\" name=\"").append( radioName).append("\"");683 sb.append("<input type=\"radio\" name=\"").append(inputName).append("\""); 632 684 sb.append(filter != null && !filterValue ? "checked" : ""); 633 685 sb.append(" value=\"false\" onclick=\"Forms.submit(event)\">").append("false"); … … 637 689 String filterValue = HTML.encodeTags(Base.getPropertyFilterString(filter, dateFormatter)); 638 690 sb.append("<input class=\"text\" type=\"text\""); 639 sb.append(" name=\" filter:").append(valueType.name()).append(":").append(getFilterproperty()).append("\"");691 sb.append(" name=\"").append(inputName).append("\""); 640 692 sb.append(" size=\"20\""); 641 693 sb.append(" maxlength=\"").append(PropertyFilter.MAX_VALUE_LENGTH).append("\""); -
trunk/www/WEB-INF/table.tld
r3679 r4250 200 200 </attribute> 201 201 <attribute> 202 <name>smartenum</name> 203 <required>false</required> 204 <rtexprvalue>true</rtexprvalue> 205 </attribute> 206 <attribute> 202 207 <name>filtervalue</name> 203 208 <required>false</required> -
trunk/www/common/plugin/index.jsp
r3995 r4250 1 <%@page import="net.sf.basedb.core.signal.SignalReceiver"%> 2 <%@page import="net.sf.basedb.core.signal.LocalSignalReceiver"%> 1 3 <%-- $Id$ 2 4 ------------------------------------------------------------------ … … 521 523 { 522 524 PluginExecutionRequest executionRequest = pluginResponse.getExecutionRequest(null); 523 Thread t = new Thread(executionRequest); 525 526 executionRequest.registerSignalReceiver(LocalSignalReceiver.getSignalReceiver("localhost:0")); 527 Thread t = new Thread(executionRequest, "immediate"); 524 528 t.setPriority(Thread.currentThread().getPriority() - 1); 525 529 t.start(); -
trunk/www/include/scripts/main.js
r4187 r4250 286 286 var charCode = event.charCode; 287 287 //if (charCode == undefined) charCode = event.which; 288 if (!charCode && event.keyCode < 32) charCode = event.keyCode; 288 if (!charCode) charCode = event.keyCode; 289 if (!charCode) charCode = event.which; 289 290 if (!charCode) charCode = 0; 290 291 return charCode; … … 294 295 this.getEventTarget = function(event) 295 296 { 296 var target = event. target;297 if (!target) target = event. srcElement;297 var target = event.srcElement; 298 if (!target) target = event.target; 298 299 return target; 299 300 } … … 317 318 } 318 319 return height; 320 } 321 322 // Get the position of an element; returns an object with 'left' and 'top' properties 323 this.getElementPosition = function(theElement) 324 { 325 var offsetTrail = theElement; 326 var offsetTop = 0; 327 var offsetLeft = 0; 328 while (offsetTrail) 329 { 330 offsetTop += offsetTrail.offsetTop; 331 offsetLeft += offsetTrail.offsetLeft; 332 offsetTrail = offsetTrail.offsetParent; 333 } 334 return {left: offsetLeft, top:offsetTop}; 319 335 } 320 336 … … 1277 1293 } 1278 1294 1295 var SmartEnum = new SmartEnumClass(); 1296 /* 1297 Handles "smart" input fields which can have an attached list of 1298 enumeration options. As the user types a popup-list is displayed 1299 with the matching options. 1300 */ 1301 function SmartEnumClass() 1302 { 1303 this.initialDelay = 300; 1304 this.repeatDelay = 50; 1305 1306 this.activeField = null; 1307 this.selected = -1; 1308 this.lastSelected = null; 1309 this.lastText = ''; 1310 1311 /* 1312 Initialise the smart enum system by creating the <div> tag that 1313 is used to hold the options. 1314 */ 1315 this.init = function() 1316 { 1317 if (this.div) return; 1318 var div = document.createElement('div'); 1319 div.className = 'smartenum'; 1320 div.style.display = 'none'; 1321 document.body.appendChild(div); 1322 this.div = div; 1323 this.debug = document.createElement('div'); 1324 document.body.appendChild(this.debug); 1325 } 1326 1327 /* 1328 Enable the input field for smart enum. Ignored if 1329 the form or field doesn't exists, the field is not an 1330 input field or if there are no options. This method 1331 changes event handlers for the input field. 1332 @param frmName The name of the form 1333 @param fieldName The name of the field 1334 @param An array object with the options 1335 */ 1336 this.enableForField = function(frmName, fieldName, options) 1337 { 1338 if (!options) return; 1339 var frm = document.forms[frmName]; 1340 if (!frm) return; 1341 var field = frm[fieldName]; 1342 if (!field) return; 1343 1344 this.init(); 1345 field.smartOptions = options; 1346 field.setAttribute('autocomplete', 'off'); 1347 Main.addClass(field, 'smartinput'); 1348 field.onfocus = this.onfocus; 1349 field.onkeyup = this.onkeyup; 1350 field.onkeydown = this.onkeydown; 1351 field.onblur = this.onblur; 1352 } 1353 1354 this.activateAndDisplay = function(formName, fieldName) 1355 { 1356 var frm = document.forms[formName]; 1357 if (!frm) return; 1358 var field = frm[fieldName]; 1359 if (!field) return; 1360 1361 if (this.blurTimerId) 1362 { 1363 clearTimeout(this.blurTimerId); 1364 this.blurTimerId = null; 1365 } 1366 this.setActive(field); 1367 this.filterOptions(true); 1368 this.showOptions(); 1369 var oldfocus = field.onfocus; 1370 field.onfocus = null; 1371 field.focus(); 1372 field.onfocus = oldFocus; 1373 } 1374 1375 /* 1376 Set a field as the active field. All other operations will 1377 now use this field. Set to null to disable all smart enum. 1378 Ignored if the field doesn't have any options. This method 1379 also positions the <div> with the options. 1380 */ 1381 this.setActive = function(field) 1382 { 1383 if (!field || !field.smartOptions) return; 1384 this.activeField = field; 1385 var pos = Main.getElementPosition(this.activeField); 1386 var div = this.div; 1387 div.style.top = (pos.top + this.activeField.offsetHeight) + 'px'; 1388 div.style.left = (pos.left-2) + 'px'; 1389 div.style.width = (this.activeField.offsetWidth + 10) + 'px'; 1390 } 1391 1392 /* 1393 Hide the enum options. 1394 */ 1395 this.hideOptions = function() 1396 { 1397 this.div.style.display = 'none'; 1398 } 1399 1400 /* 1401 Show the enum options setting the correct position. 1402 */ 1403 this.showOptions = function() 1404 { 1405 this.div.style.display = 'block'; 1406 } 1407 1408 /* 1409 Filter the enum options by the text in the active field. 1410 The options that passed the filter are added as <div> tags 1411 to the enum <div>. 1412 @return TRUE if the filter generated any options, FALSE otherwise 1413 */ 1414 this.filterOptions = function(allowEmpty) 1415 { 1416 if (!this.activeField) return false; 1417 var text = this.activeField.value.replace(/^[=!<>]*/, ''); 1418 if (text == this.lastMatchedText) return true; 1419 if (text == '' && !allowEmpty) return false; 1420 1421 var options = this.activeField.smartOptions; 1422 this.lastMatchedText = text; 1423 this.selected = -1; 1424 this.lastSelected = null; 1425 var matching = ''; 1426 var index = 0; 1427 for (var i = 0; i < options.length; i++) 1428 { 1429 if (options[i].indexOf(text) >= 0) 1430 { 1431 matching += '<div class="smartoption" id="smartoption.' + index + '"'; 1432 matching += ' onmouseover="SmartEnum.setSelectedOption(' + index + ')"'; 1433 matching += ' onclick="SmartEnum.submitSelected()">' + options[i] + '</div>'; 1434 index++; 1435 } 1436 } 1437 this.div.innerHTML = matching; 1438 return true; 1439 } 1440 1441 /* 1442 Mark a specific enum option as selected. Also makes sure 1443 that the selected option is within the viewable area. 1444 @param index The index of the option 1445 */ 1446 this.setSelectedOption = function(index) 1447 { 1448 if (this.lastSelected) 1449 { 1450 Main.removeClass(this.lastSelected, 'selected'); 1451 this.lastSelected = null; 1452 } 1453 var option = document.getElementById('smartoption.' + index); 1454 if (option) 1455 { 1456 Main.addClass(option, 'selected'); 1457 this.lastSelected = option; 1458 this.selected = index; 1459 var optionTop = option.offsetTop; 1460 var optionBottom = optionTop + option.offsetHeight; 1461 var parent = option.offsetParent; 1462 var parentTop = parent.scrollTop; 1463 var parentBottom = parentTop + parent.offsetHeight; 1464 if (optionTop < parentTop) 1465 { 1466 parent.scrollTop = optionTop; 1467 } 1468 else if (optionBottom > parentBottom) 1469 { 1470 parent.scrollTop = optionBottom - parent.offsetHeight; 1471 } 1472 } 1473 } 1474 1475 /* 1476 Moves the selection up or down, optionally 1477 repeating the operation at specified time intervals. 1478 @param delta The number of options to shift the selection 1479 @param delayRepeat Number of milliseconds to wait until 1480 the move is repeated for the first time 1481 @param repeat Number of milliseconds to wait between 1482 subsequent repeats 1483 */ 1484 this.moveSelection = function(delta, delayRepeat, repeat) 1485 { 1486 var option = document.getElementById('smartoption.' + (this.selected + delta)); 1487 if (option) 1488 { 1489 this.setSelectedOption(this.selected + delta); 1490 } 1491 if (delayRepeat && repeat) 1492 { 1493 var call = 'SmartEnum.moveSelection(' + delta + ',' + repeat + ',' + repeat + ')'; 1494 this.timerId = setTimeout(call, delayRepeat); 1495 } 1496 } 1497 1498 /* 1499 Copies the selected option to the active field and submits 1500 the form. If no option is selected, just submit the form. 1501 */ 1502 this.submitSelected = function(event) 1503 { 1504 if (!this.activeField) return; 1505 if (this.lastSelected) 1506 { 1507 var text = this.activeField.value; 1508 var selectedText = this.lastSelected.innerHTML; 1509 this.activeField.value = text.replace(/^([=!<>]*).*/, '$1' + selectedText); 1510 } 1511 this.activeField.form.submit(); 1512 } 1513 1514 /* 1515 Cancels a move selection repeat set in the 'moveSelection' method. 1516 */ 1517 this.cancelKeyRepeat = function() 1518 { 1519 if (this.timerId) 1520 { 1521 clearTimeout(this.timerId); 1522 this.timerId = null; 1523 } 1524 } 1525 1526 /* 1527 Called when a smart-enum enabled field receivs 1528 the focus. This should set the current field to 1529 the active field. 1530 */ 1531 this.onfocus = function(event) 1532 { 1533 if (!event) event = window.event; 1534 var field = Main.getEventTarget(event); 1535 SmartEnum.setActive(field); 1536 } 1537 1538 /* 1539 Called when a smart-enum enabled field loses 1540 the focus. This should hide the options and 1541 set the current field to null. 1542 */ 1543 this.onblur = function(event) 1544 { 1545 if (!event) event = window.event; 1546 // Need timout, otherwise the options are hidden and can't receive 1547 // a possible mouseclick that selects an options and submits the form. 1548 SmartEnum.blurTimerId = setTimeout('SmartEnum.hideOptions(); SmartEnum.setActive(null);', 100); 1549 } 1550 1551 /* 1552 Called when a key is pressed in a smart-enum enabled field. 1553 This function detects: 1554 * up/down arrow: moves the selected option 1555 * enter: submits the form 1556 */ 1557 this.onkeydown = function(event) 1558 { 1559 if (!event) event = window.event; 1560 var charCode = Main.getEventCharCode(event); 1561 if (charCode == 38) 1562 { 1563 // Up arrow 1564 SmartEnum.moveSelection(-1, SmartEnum.initialDelay, SmartEnum.repeatDelay); 1565 } 1566 else if (charCode == 40) 1567 { 1568 // Down arrow 1569 SmartEnum.moveSelection(1, SmartEnum.initialDelay, SmartEnum.repeatDelay); 1570 } 1571 else if (charCode == 13) 1572 { 1573 // Enter 1574 SmartEnum.submitSelected(event); 1575 } 1576 } 1577 1578 /* 1579 Called when a key is released in a smart-enum enabled field. 1580 This function detects changes to the text and displays matching 1581 options. 1582 */ 1583 this.onkeyup = function(event) 1584 { 1585 if (!event) event = window.event; 1586 SmartEnum.cancelKeyRepeat(); 1587 var charCode = Main.getEventCharCode(event); 1588 if (SmartEnum.filterOptions(charCode == 40 || charCode == 38)) 1589 { 1590 SmartEnum.showOptions(); 1591 } 1592 else 1593 { 1594 SmartEnum.hideOptions(); 1595 } 1596 } 1597 1598 } 1599 1279 1600 var Forms = new FormClass(); 1280 1601 // Functions related to form handling 1281 1602 function FormClass() 1282 1603 { 1604 1283 1605 /* 1284 1606 Attach this function to the onkeypress attribute of a field to -
trunk/www/include/styles/main.css
r3820 r4250 348 348 padding: 2px; 349 349 } 350 351 .smartenum { 352 position: absolute; 353 width: 100px; 354 height: 200px; 355 background: #E0E0E0; 356 border-top: 1px solid #333333; 357 border-left: 1px solid #333333; 358 border-right: 1px solid #333333; 359 border-bottom: 1px solid #333333; 360 padding: 2px; 361 z-index: 999; 362 overflow: auto; 363 } 364 365 .smartinput { 366 border-top: 2px groove #999999; 367 border-left: 2px groove #999999; 368 border-bottom: 2px ridge #FFFFFF; 369 border-right: 2px ridge #FFFFFF; 370 371 } 372 373 .smartinput input { 374 border: 0px; 375 } 376 377 .smartoption { 378 cursor: pointer; 379 } 380 381 .smartimage { 382 cursor: pointer; 383 border-left: 1px solid #999999; 384 background: #ffffff; 385 } 386 387 .smartenum .selected { 388 background: #cccccc; 389 }
Note: See TracChangeset
for help on using the changeset viewer.