diff --git a/core/src/main/java/hudson/model/AutoCompletionCandidates.java b/core/src/main/java/hudson/model/AutoCompletionCandidates.java new file mode 100644 index 0000000000..10888d2094 --- /dev/null +++ b/core/src/main/java/hudson/model/AutoCompletionCandidates.java @@ -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. + *

+ * This object should be returned from your doAutoCompleteXYZ methods. + * + * @author Kohsuke Kawaguchi + */ +public class AutoCompletionCandidates implements HttpResponse { + private final List values = new ArrayList(); + + 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); + } +} diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 482522abb4..eb8b75d29d 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -357,6 +357,19 @@ public abstract class Descriptor> implements Saveable { return depends; } + /** + * Computes the auto-completion setting + */ + public void calcAutoCompleteSettings(String field, Map 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. */ diff --git a/core/src/main/resources/lib/form/textbox.jelly b/core/src/main/resources/lib/form/textbox.jelly index c2ce2b43d7..1461bd1f13 100644 --- a/core/src/main/resources/lib/form/textbox.jelly +++ b/core/src/main/resources/lib/form/textbox.jelly @@ -61,10 +61,11 @@ THE SOFTWARE. + ${descriptor.calcAutoCompleteSettings(field,attrs)} + + + +

+ + + + +
+
+ + + diff --git a/war/resources/scripts/hudson-behavior.js b/war/resources/scripts/hudson-behavior.js index 9bd5813101..1b26aa8041 100644 --- a/war/resources/scripts/hudson-behavior.js +++ b/war/resources/scripts/hudson-behavior.js @@ -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");