提交 2c354a5f 编写于 作者: K Kohsuke Kawaguchi

Finalizing the apply button support.

Added server side utilities to generate apply-aware responses.
上级 7806553f
......@@ -30,6 +30,8 @@ import hudson.XmlFile;
import hudson.BulkChange;
import hudson.Util;
import hudson.model.listeners.SaveableListener;
import hudson.util.FormApply;
import hudson.util.QuotedStringTokenizer;
import hudson.util.ReflectionUtils;
import hudson.util.ReflectionUtils.Parameter;
import hudson.views.ListViewColumn;
......@@ -44,6 +46,7 @@ import org.jvnet.tiger_types.Types;
import org.apache.commons.io.IOUtils;
import static hudson.Functions.*;
import static hudson.util.QuotedStringTokenizer.*;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import javax.servlet.ServletException;
import javax.servlet.RequestDispatcher;
......@@ -957,8 +960,13 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
}
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
// for now, we can't really use the field name that caused the problem.
new Failure(getMessage()).generateResponse(req,rsp,node);
if (FormApply.isApply(req)) {
FormApply.applyResponse("notificationBar.show(" + quote(getMessage())+ ",notificationBar.defaultOptions.ERROR)")
.generateResponse(req, rsp, node);
} else {
// for now, we can't really use the field name that caused the problem.
new Failure(getMessage()).generateResponse(req,rsp,node);
}
}
}
......
......@@ -48,7 +48,9 @@ import hudson.util.ColorPalette;
import hudson.util.CopyOnWriteList;
import hudson.util.DataSetBuilder;
import hudson.util.DescribableList;
import hudson.util.FormApply;
import hudson.util.Graph;
import hudson.util.HttpResponses;
import hudson.util.IOException2;
import hudson.util.RunList;
import hudson.util.ShiftedCategoryAxis;
......@@ -986,7 +988,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
Jenkins.checkGoodName(newName);
rsp.sendRedirect("rename?newName=" + URLEncoder.encode(newName, "UTF-8"));
} else {
rsp.sendRedirect(".");
FormApply.success(".").generateResponse(req, rsp, null);
}
} catch (JSONException e) {
StringWriter sw = new StringWriter();
......
/*
* The MIT License
*
* Copyright (c) 2012-, CloudBees, 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.util;
import org.kohsuke.stapler.HttpResponses.HttpResponseException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
/**
* Server-side code related to the &lt;f:apply> button.
*
* @author Kohsuke Kawaguchi
*/
public class FormApply {
/**
* Generates the response for the form submission in such a way that it handles the "apply" button
* correctly.
*
* @param destination
* The page that the user will be taken to upon a successful submission (in case this is not via the "apply" button.)
*/
public static HttpResponseException success(final String destination) {
return new HttpResponseException() {
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
if (isApply(req)) {
// if the submission is via 'apply', show a response in the notification bar
applyResponse("notificationBar.show('"+Messages.HttpResponses_Saved()+"',notificationBar.defaultOptions.OK)")
.generateResponse(req,rsp,node);
} else {
rsp.sendRedirect(destination);
}
}
};
}
/**
* Is this submission from the "apply" button?
*/
public static boolean isApply(StaplerRequest req) {
return Boolean.parseBoolean(req.getParameter("core:apply"));
}
/**
* Generates the response for the asynchronous background form submission (AKA the Apply button.)
* <p>
* When the response HTML includes a JavaScript function in a pre-determined name, that function gets executed.
* This method generates such a response from JavaScript text.
*/
public static HttpResponseException applyResponse(final String script) {
return new HttpResponseException() {
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
rsp.setContentType("text/html;charset=UTF-8");
rsp.getWriter().println("<html><body><script>" +
"window.applyCompletionHandler = function (w) {" +
" with(w) {" +
script +
" }" +
"};" +
"</script></body></html>");
}
};
}
}
......@@ -25,4 +25,5 @@ ClockDifference.Ahead=\ ahead
ClockDifference.Behind=\ behind
ClockDifference.Failed=Failed to check
FormValidation.ValidateRequired=Required
FormValidation.Error.Details=(show details)
\ No newline at end of file
FormValidation.Error.Details=(show details)
HttpResponses.Saved=Saved
\ No newline at end of file
......@@ -26,6 +26,8 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:s="jelly:stapler" xmlns:d="jelly:define" xmlns:f="/lib/form">
<s:documentation>
"Apply" button that submits the form but without a page transition.
See hudson.util.FormApply for the server-side code.
</s:documentation>
<input type="button" value="${%Apply}" class="applyButton" success="${%Saved}" />
<input type="hidden" name="core:apply" value="" />
<input type="button" value="${%Apply}" class="applyButton" />
</j:jelly>
\ No newline at end of file
......@@ -589,11 +589,21 @@ var hudsonRules = {
},
"INPUT.applyButton":function (e) {
var successText = e.getAttribute("success");
var target = document.createElement("iframe");
target.style.display = "none";
target.id = target.name = "iframe"+(iota++);
document.body.appendChild(target);
var id = "iframe"+(iota++);
var responseDialog = new YAHOO.widget.Panel("wait"+(iota++), {
fixedcenter:true,
close:true,
draggable:true,
zindex:4,
modal:true,
visible:false
});
responseDialog.setHeader("Error");
responseDialog.setBody("<iframe id='"+id+"' name='"+id+"' style='height:100%; width:100%'></iframe>");
responseDialog.render(document.body);
var target = $(id); // iframe
function attachIframeOnload(target, f) {
if (target.attachEvent) {
......@@ -604,22 +614,33 @@ var hudsonRules = {
}
var attached = false;
makeButton(e,function (e) {
var f = findAncestor(e.target, "FORM");
if (!attached) {
attached = true;
attachIframeOnload(target, function () {
notificationBar.show(successText,notificationBar.defaultOptions.OK)
if (target.contentWindow && target.contentWindow.applyCompletionHandler) {
// apply-aware server is expected to set this handler
target.contentWindow.applyCompletionHandler(window);
} else {
// otherwise this is possibly an error from the server, so we need to render the whole content.
var r = YAHOO.util.Dom.getClientRegion();
responseDialog.cfg.setProperty("width",r.width*3/4+"px");
responseDialog.cfg.setProperty("height",r.height*3/4+"px");
responseDialog.center();
responseDialog.show();
}
});
}
f.target = target.id;
f.elements['core:apply'].value = "true";
try {
buildFormTree(f);
f.submit();
} finally {
f.elements['core:apply'].value = null;
f.target = null;
}
});
......@@ -2580,7 +2601,10 @@ var layoutUpdateCallback = {
}
}
// notification bar
// Notification bar
// ==============================
// this control displays a single line message at the top of the page, like StackOverflow does
// see ui-samples for more details
var notificationBar = {
OPACITY : 0.8,
DELAY : 3000, // milliseconds to auto-close the notification
......@@ -2591,6 +2615,11 @@ var notificationBar = {
OK : {
icon: "accept.png",
backgroundColor: "#8ae234"
},
ERROR : {
icon: "red.png",
backgroundColor: "#ef2929",
sticky: true
}
},
......@@ -2638,6 +2667,7 @@ var notificationBar = {
this.clearTimeout();
var self = this;
this.token = window.setTimeout(function(){self.hide();},this.DELAY);
if (!options.sticky)
this.token = window.setTimeout(function(){self.hide();},this.DELAY);
}
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册