I am working on jsp,
What I am trying to implement is quite simple.
do some time-consuming work with Java
while processing, show users the spinner
So I have implemented like below
<%# page contentType="text/html; charset=UTF-8" %>
<%# page isThreadSafe="true" %>
<%
boolean isFinish = false;
Thread executeThread = new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i < 10; i++){
try{
System.out.println(i + " Thread ");
Thread.sleep(1000);
}catch(Exception ex){
System.err.println(ex);
}
}
}
});
executeThread.run();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Loading</title>
</head>
<body>
<div class="popup" style="text-align: center;">
<div class="l_img">
<img src="resources/image/spinner/loading_gif.gif" alt="LOADING...">
</div>
<div class="b_txt">Processing</div>
<div class="s_txt">Please, wait..</div>
</div>
</body>
<%
if(isFinish){
%>
<script>
alert('done');
</script>
<%
}
%>
</html>
However, page shows up after Thread has terminated. Could I reverse the order?
What I wanted in order
show html page(spinner gif)
execute Java logics
catch the return of Java execution
if return is true, then alert with javascript
Is it possible?
Thanks for your answers
You can't do a server-side operation change dinamically the render the page.
the page will be rendered always where if(isFinish) has been executed.
the server will send the complete html page to the user only when all the java has been executed and in one block! you need to implement it on the front-end, for example you send a starting basic page of loading and you call the long term process with a ajax call or something similar.
<!DOCTYPE html>
<html>
<body onload="alert('done')">
Put your spinner here.
Some text here is necessary here for the browser to start displaying.
Otherwise it will wait until it receives enough of a response to begin displaying anything.
I am not sure how much is necessary. This works for me.
<%
out.print("<br/>Starting processing now. <br/>");
out.flush();
Thread.sleep(2000);
out.print("<br/>Processing..... <br/>");
out.flush();
for(int x = 1; x < 4; x++){
Thread.sleep(2000);
out.print("Result " + x + ".<br/>");
out.flush();
}
%>
</body>
</html>
Related
I need a ASP.net application which is only kind of "pageDisplayer" from content which is coming from an API. So I choose ASP.net Webform and tried the following:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="PMLetterAcceptance.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:Literal runat="server" id="JavaScript"></asp:Literal>
</head>
<body>
<form id="letterform" runat="server">
<div>
<%= pageContent %>
</div>
</form>
</body>
public partial class WebForm1 : System.Web.UI.Page
{
protected string pageContent = "";
protected void Page_Load(object sender, EventArgs e)
{
...// here I fetch the html and javascript content from the API
dynamic json = Json.Decode(streamReader.ReadToEnd());
if (json.status != "OK")
pageContent = json.error;
else
pageContent = json.html;
JavaScript.Text = json.script;
}
}
The html content and the script are loaded correct but I cannot access DOM elements in the javascript. The javascript looks like that
(function()
{
function processForm(e)
{
... // Here I want to do some stuff before sending the form
}
let form = document.getElementById('letterform');
if (form.attachEvent)
form.attachEvent("submit", processForm);
else
form.addEventListener("submit", processForm);
})();
No I get the error "form is null". For me it looks like the javascript is executed before the DOM is ready. But how can I change this to make it work like expected?
Try putting the JS (literal) at the bottom of the page, before the closing body tag. That way, the HTML will be loaded before the JS tries to find elements.
I am trying to build a progressbar trying to periodically run an ajax call from the client side while a postback is occuring.
However, it seems like the ajax call gets blocked, maybe because of to the postback. When the postback is finished, the http request with the ajax calls goes from pending to canceled.
Questions:
Is it impossible to issue ajax calls during postback?
Can I use the Session like I am doing in the following code example to keep track of the progress?
The webpage aspx:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="TestProgressIndicator.aspx.cs"
Inherits="Test.TestProgressIndicator" %>
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-3.2.1.min.js"
type="text/javascript"></script>
<script type="text/javascript">
function start_progress()
{
var indicator = $(".progress-indicator");
indicator.show();
var num_div = indicator.find(".num");
num_div.text("0%");
setTimeout(update_progress, 80);
function update_progress()
{
console.log("update_progress");
$.post(
"Ajax/ProgressBarCallback.aspx"
, function (progress)
{
num_div.text(progress + "%");
if (progress < 100)
setTimeout(update_progress, 80);
else
indicator.hide();
});
}
}
</script>
</head>
<body>
<form runat="server">
<asp:ScriptManager runat="server"/>
<div class="progress-indicator">
<div class="num"></div>
</div>
<asp:Button ID="btnStart" runat="server" Text="Starta"
OnClientClick="start_progress()" OnClick="btnStart_OnClick" />
</form>
</body>
</html>
Ajax/ProgressBarCallback.aspx:
<%# Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
var progressObj = HttpContext.Current.Session["progress"];
var progress = progressObj != null ? int.Parse(progressObj.ToString()) : 0;
Response.ContentType = "text/json";
Response.Write(progress);
}
</script>
I am aware of this post being a duplicate of ASP.NET making AJAX calls during long Postback but it was 5 years since asked and it did not get any explanatory answers.
I've successfully invoked a web service when loading a jsp page. The issue I'm facing is setting up a user to be able to press a button to invoke a different method on that same web service. The function "getSS()" is supposed to accomplish this, but I suppose that javascript doesn't directly read that type of invocation. I've found solutions that call up the web service and pass a parameter to it, but those are usually not calling up specific methods within the webservice.
Here is my code, what can I put in the "getSS()" function to accomplish this? I've already loaded jQuery, and the web service is written in java. Note, I already wrote the code to do all the work, I just need to know how to call that specific code. None of the other solutions seem to fit my needs.
<%--
Document : index
Created on : May 6, 2016, 9:39:44 AM
Author : mmarino
--%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script type="text/javascript">
function getSS(){
var e = document.getElementById("names");
var daString = e.options[e.selectedIndex].value;
try {
org.me.calculator.CalculatorWS_Service service = new org.me.calculator.CalculatorWS_Service();
org.me.calculator.CalculatorWS port = service.getCalculatorWSPort();
// TODO process result here
java.lang.String result = port.SS(daString);
document.getElementById('inputhere').innerHTML = "hi";
} catch (Exception ex) {
// TODO handle custom exceptions here
document.getElementById('inputhere').innerHTML = ex;
}
}
</script>
</head>
<body>
<h1>Hello World!</h1> <%-- start web service invocation --%><hr/>
<button value="hi" onclick="getSS()"> Click</button>
<select id="names">
<%
try {
org.me.calculator.CalculatorWS_Service service = new org.me.calculator.CalculatorWS_Service();
org.me.calculator.CalculatorWS port = service.getCalculatorWSPort();
// TODO process result here
java.lang.String result = port.getNames();
out.println(result);
} catch (Exception ex) {
// TODO handle custom exceptions here
}
%>
<%-- end web service invocation --%>
</select>
<hr/>
<div id="inputhere">Hi.</div>
</body>
So it seemed all I was missing was setting that java code to a variable and putting the proper opening and closing statements:
function doIt(){
<%-- start web service invocation --%>
var x = <%
try {
org.me.testbilling.TestBillingWS_Service service = new org.me.testbilling.TestBillingWS_Service();
org.me.testbilling.TestBillingWS port = service.getTestBillingWSPort();
// TODO initialize WS operation arguments here
java.lang.String name = "Marcel" ;
// TODO process result here
java.lang.String result = port.getSS(name);
out.println(result);
} catch (Exception ex) {
// TODO handle custom exceptions here
}
%>
<%-- end web service invocation --%>
alert(x);
}
</script>
Still not quite sure how to make that "java.lang.String name =" be set to a javascript variable.
I have a jsp page that looks like the following:
What the intent is, is to get the current environment via a system variable and then generate the correct url for that environment.
<%# taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%# taglib prefix="logic" uri="http://struts.apache.org/tags-logic" %>
<%
String sysEnv = "";
if(System.getProperty("env.name").equals("test")) {
sysEnv = "test";
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html>
<head>
<%# include file="/includes/common.jsp" %>
<script type="text/javascript" src="<c:out value="${requestScope.scriptsLocation}"/>/scripts/general.js"></script>
<c:if test="${requestScope.isFeed == true}">
<jsp:include page="/includes/someInclude.jsp"/>
<script src="http://www.myothersite.com/feed/d/some.js" type="text/javascript"></script>
<script type="text/javascript">
var environ = <%=sysEnv%>;
if(environ == 'test'){
var theUrl = 'http://mywebsite.com?isFeed=true&env=TEST';
} else {
var theUrl = 'http://mywebsite.com?isFeed=true';
}
...
</script>
...
I think I'm supposed to have the tags-logic import to do the looping that I'm trying to achieve in Java, but this is not working.
Since you're already in a JSP why not just do (roughly) this:
<script>
var url = 'http://mywebsite.com?isFeed=true';
if ('<%= System.getProperty("env.name") %>' === 'test') {
url += '&env=TEST';
}
// etc.
Personally I'd move this logic out of the view and create a request-scoped attribute in a filter, as part of your Struts 1 request processor, etc. since scriptlets are almost always bad. It also gives you the opportunity to set it at runtime.
In addition, the URL generation should also likely be moved out of the view layer.
I have two pages one is the main page and the another one is the inner page:
Page names: main.jsp , sidebar.jsp
I want to call the onload function on both of these pages. Is that possible. If yes How?
Below is the code for main.jsp:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# include file="/pages/common/init.jsp"%>
<%# taglib prefix="sx" uri="/struts-dojo-tags"%>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>J.C. Taylor - Broker Website</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="/css/default.css" media="screen" type="text/css" />
</head>
<body onload="prepopulateFields();load(17);">
<s:form name="continue" id="continue_id" action="continue" method="POST" validate="true" enctype="multipart/form-data">
<div id="wrapper">
<div id="main">
<div id="sidebar">
<%# include file="/pages/common/sidebar.jsp"%>
<span class="clearIt"></span>
</div>
The sidebar.jsp is:
<body onload="setSelected();">
//Some static content here
</body>
So Basically I want is to call prepopulateFields() Javascript method which belongs to onload() event of the main .jsp page and setSelected() which belongs to onload() method of the sidebar.jsp symulatneously and separately.
I know I can call the setSelected(); method inside the prepopulateFields() method but that I dont want to do. All I want is when the page is loaded both the onload functions should be called separately.
If you have some suggestions please do let me know!
I know I am being little bit ridiculous here but if I could do that My job will be very easy.
i don't think you can call more than one onload function.
best way is to call the method from already called function
function prepopulateFields(){
if //condition which check the current page where you want other onload function
setSelected();
}
<body onload="prepopulateFields();load(17);">
</body>
You cannot nest HTML <body> elements, it would only malform HTML.
Best is to put it as a <script> at the bottom of sidebar.jsp.
<script type="text/javascript">setSelected()</script>
If you use firebug to inspect the rendered html page of main.jsp. You would see there is only one < body > element. The < body > element in your sidebar.jsp is not rendered since it will malform HTML as html or body not allowed in included jsp.
Be careful that the included file does not contain <html>, </html>, <body>, or </body> tags
The solution is:
either put your setSelected() into main.jsp body onload event if the sidebar.jsp is always loaded;
or do as BalusC suggested.
window.onload = codeAddress; should work. Here's a demo. And the full code:
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
Put the class definition in the parent jsp, and instantiate as many onloads as you need in the includes.
<SCRIPT>
// this portion was placed above the Class definition for convenience.
// make sure the Class definition gets loaded first in your code.
new OnLoad(function(){
alert("document loaded");
},100);
</SCRIPT>
...
<SCRIPT>
// Class Definition
OnLoad = function(taskFunction,miliseconds) {
var context = this;
context.cnt = 0;
context.id = null;
context.doTask=taskFunction;
context.interval = function() {
if(document.readyState == "complete"){
try{ context.stop();} catch(e){ throw new Error("stop error: " + context.id); }
try{ context.doTask();} catch(e){ throw new Error("load error: " + context.id); }
}
};
context.start = function(timing) {
if(context.id && context.id!=null)
context.stop();
context.cnt=0;
context.id=setInterval(context.interval,timing);
};
context.stop = function() {
var _id = context.id;
clearInterval(context.id);
context.id=null;
};
context.start(miliseconds ? miliseconds : 100);
};
</SCRIPT>