Auto-completion can be now easily added to text boxes by plugins.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@34002 71c3de6d-444a-0410-be80-ed276b4c234a
This commit is contained in:
kohsuke committed 2010-08-20 23:04:33 +00:00
1 parent 1c78940275
commit dfdcecccb1
6 files changed
+253 -1

No files matched your search

@@ -0,0 +1,66 @@
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model;
import hudson.search.Search;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Flavor;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Data representation of the auto-completion candidates.
* <p>
* This object should be returned from your doAutoCompleteXYZ methods.
*
* @author Kohsuke Kawaguchi
*/
public class AutoCompletionCandidates implements HttpResponse {
private final List<String> values = new ArrayList<String>();
public AutoCompletionCandidates add(String v) {
values.add(v);
return this;
}
public AutoCompletionCandidates add(String... v) {
values.addAll(Arrays.asList(v));
return this;
}
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object o) throws IOException, ServletException {
Search.Result r = new Search.Result();
for (String value : values) {
r.suggestions.add(new hudson.search.Search.Item(value));
}
rsp.serveExposedBean(req,r, Flavor.JSON);
}
}
@@ -357,6 +357,19 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
return depends;
}
/**
* Computes the auto-completion setting
*/
public void calcAutoCompleteSettings(String field, Map<String,Object> attributes) {
String capitalizedFieldName = StringUtils.capitalize(field);
String methodName = "doAutoComplete" + capitalizedFieldName;
Method method = ReflectionUtils.getPublicMethodNamed(getClass(), methodName);
if(method==null)
return; // no auto-completion
attributes.put("autoCompleteUrl", String.format("%s/%s/autoComplete%s", getCurrentDescriptorByNameUrl(), getDescriptorUrl(), capitalizedFieldName));
}
/**
* Used by Jelly to abstract away the handlign of global.jelly vs config.jelly databinding difference.
*/
@@ -61,10 +61,11 @@ THE SOFTWARE.
</st:attribute>
</st:documentation>
<f:prepareDatabinding />
${descriptor.calcAutoCompleteSettings(field,attrs)} <!-- this figures out the 'autoCompleteUrl' attribute -->
<!-- mostly pass-through all the attributes -->
<m:input xmlns:m="jelly:hudson.util.jelly.MorphTagLibrary"
class="setting-input ${attrs.checkUrl!=null?'validated':''} ${attrs.clazz}"
class="setting-input ${attrs.checkUrl!=null?'validated':''} ${attrs.autoCompleteUrl!=null?'auto-complete':null} ${attrs.clazz}"
name="${attrs.name ?: '_.'+attrs.field}"
value="${attrs.value ?: instance[attrs.field] ?: attrs.default}"
type="text"
@@ -0,0 +1,113 @@
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.plugins.ui_samples;
import hudson.Extension;
import hudson.model.AutoCompletionCandidates;
import org.kohsuke.stapler.QueryParameter;
/**
* Adding auto-completion to the text box.
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class AutoCompleteTextBox extends UISample {
@Override
public String getDescription() {
return "Provide auto-completion to the text box";
}
@Extension
public static final class DescriptorImpl extends UISampleDescriptor {
/**
* This method provides auto-completion items for the 'state' field.
* Stapler finds this method via the naming convention.
*
* @param value
* The text that the user entered.
*/
public AutoCompletionCandidates doAutoCompleteState(@QueryParameter String value) {
AutoCompletionCandidates c = new AutoCompletionCandidates();
for (String state : STATES)
if (state.toLowerCase().startsWith(value.toLowerCase()))
c.add(state);
return c;
}
}
private static final String[] STATES = new String[]{
"Alabama",
"Alaska",
"Arizona",
"Arkansas",
"California",
"Colorado",
"Connecticut",
"Delaware",
"Florida",
"Georgia",
"Hawaii",
"Idaho",
"Illinois",
"Indiana",
"Iowa",
"Kansas",
"Kentucky",
"Louisiana",
"Maine",
"Maryland",
"Massachusetts",
"Michigan",
"Minnesota",
"Mississippi",
"Missouri",
"Montana",
"Nebraska",
"Nevada",
"New Hampshire",
"New Jersey",
"New Mexico",
"New York",
"North Carolina",
"North Dakota",
"Ohio",
"Oklahoma",
"Oregon",
"Pennsylvania",
"Rhode Island",
"South Carolina",
"South Dakota",
"Tennessee",
"Texas",
"Utah",
"Vermont",
"Virginia",
"Washington",
"West Virginia",
"Wisconsin",
"Wyoming"
};
}
@@ -0,0 +1,36 @@
<!--
~ The MIT License
~
~ Copyright (c) 2010, InfraDNA, Inc.
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:s="/lib/samples">
<s:sample title="Dynamic ComboBox Sample">
<form>
<table>
<f:entry title="U.S. State" field="state">
<f:textbox />
</f:entry>
</table>
</form>
</s:sample>
</j:jelly>
+23
View File
@@ -586,6 +586,29 @@ var hudsonRules = {
registerRegexpValidator(e,/^(\d*[1-9]\d*|)$/,"Not a positive number");
},
"INPUT.auto-complete": function(e) {// form field with auto-completion support
// insert the auto-completion container
var div = document.createElement("DIV");
e.parentNode.insertBefore(div,e.nextSibling);
e.style.position = "relative"; // or else by default it's absolutely positioned, making "width:100%" break
var ds = new YAHOO.widget.DS_XHR(e.getAttribute("autoCompleteUrl"),["suggestions","name"]);
ds.scriptQueryParam = "value";
// Instantiate the AutoComplete
var ac = new YAHOO.widget.AutoComplete(e, div, ds);
ac.prehighlightClassName = "yui-ac-prehighlight";
ac.animSpeed = 0;
ac.useShadow = true;
ac.autoSnapContainer = true;
ac.doBeforeExpandContainer = function(textbox,container) {// adjust the width every time we show it
container.style.width=textbox.clientWidth+"px";
var Dom = YAHOO.util.Dom;
Dom.setXY(container, [Dom.getX(textbox), Dom.getY(textbox) + textbox.offsetHeight] );
return true;
}
},
"A.help-button" : function(e) {
e.onclick = function() {
var tr = findFollowingTR(this, "help-area");