I want to set a JavaScript variable from JSP without causing the entire page to reload. The code I have now sets the variable, but reloads the entire page as a side effect.
example.jsp:
<html>
<select name="country" id="country"onchange="getCountryI()">
<option value="">Select</option>
<option value="india">India</option>
<option value="aus">Austrila</option>
<option value="uk">U.K</option>
<option value="eng">England</option>
<option value="westindies">West-Indies</option>
</select>
</html>
<script>
function getCountryI() {
alert(3);
var id = document.getElementById("country").value;
window.location.replace("example.jsp?name=" + id);
}
</script>
<%
String value = request.getParameter("name");
System.out.println("value is" + value);
out.println("valuevaluevalue" + value);
%>
Once you've downloaded the page, the only ways to update a local (in-page) variable from the server is to
a) reload the page, or
b) use AJAX (JSON/P, preferably) to get the variable.
HTTP is sessionless, which means that the server-side has no way to provide data to the page on the end-user browser unless the browser initiates contact. (Web/browser sockets aside, since they're HTML5-only. Do you really want the server side keeping a list of all the browsers that have ever needed a response and writing code to age them off? If you do, go right ahead--but it's easier to just AJAX it.)
I don't thing the problem is inside <%%>.
The event onChange has been called and this code is "refreshing" the page. (actually changing location)
window.location.replace("example.jsp?name=" + id);
Try debug.
This part is invalid :
<script>
function getCountryI() {
alert(3);
var id = document.getElementById("country").value;
window.location.replace("example.jsp?name=" + id);
}
<%
String value = request.getParameter("name");
System.out.println("value is" + value);
out.println("valuevaluevalue" + value);
%>
</script>
The out.println will add invalid script content in the rendered page after refresh, also it will not be shown.
The <% %> part should be moved out of the script like this :
<script>
function getCountryI() {
alert(3);
var id = document.getElementById("country").value;
window.location.replace("example.jsp?name=" + id);
}
</script>
<%
String value = request.getParameter("name");
System.out.println("value is" + value);
out.println("valuevaluevalue" + value);
%>
You could use old-school Ajax:
<form action="..." method="..." target="foo">
...
<input type="submit" value="Submit">
</form>
<iframe id="foo"></iframe>
You could attach an onload event handler to the iframe so you can extract any info that you want:
var foo = null;
var iframe = document.getElementById("foo");
iframe.addEventListener("load", function() {
var win = iframe.contentWindow || iframe.contentDocument;
foo = win.foo
});
The response in the IFRAME could have a normal <script> tag that sets a global variable in that document, which you can access from the parent window.
EDIT: The key here is the target attribute on the FORM tag contains the value of the id on the IFRAME. That will cause the form to submit to the IFRAME, and load the response in the IFRAME.
Related
I have a main page with a popup window.
<textarea class="form-control item"></textarea>
<button type="button" class="btn btn-primary" name="name">Send</button>
There is also a second page. (/conclusion/main)
<textarea id="retro" style="height: 200px; width: 800px"></textarea>
I enter the text in the window and send. The window should close and the text should be sent to the second page and the text should be saved in the field "textarea". Even if they close the page or reload, the text should remain in the second page.
This code allows you to save, but after closing the page, does not save
(function(){
var textarea = document.getElementById('retro');
if (localStorage.retro)
{
textarea.value = localStorage.retro;
}
textarea.onchange = function()
{
localStorage.retro = this.value;
}
})();
Sends from the first page to the second
function getParams(){
var idx = document.URL.indexOf('?');
var params = new Array();
if (idx != -1) {
var pairs = document.URL.substring(idx+1, document.URL.length).split('&');
for (var i=0; i<pairs.length; i++){
nameVal = pairs[i].split('=');
params[nameVal[0]] = nameVal[1];
}
}
return params2;
}
params = getParams();
name = unescape(params["name"]);
document.getElementById('retro').innerHTML = name;
There are some questions around what you are trying to do here. What I have done is broken this down into 2 parts
Passing the local storage between 2 pages and accessing it.
Decoding Parameters in the URL and assigning them
Some assumptions that I made:
I have noticed some of the classes from bootstrap so i assume that you have jQuery on the page and also you may know how to use it.
Using chrome for testing this
PART 1 - Passing localstorage between windows:
First thing to note is you may be better using a cookie library (js-cookie) or creating one yourself that you can access. As localstorage may well be insecure depending on what data you want to store in there.
With that out of the way, you were on the right track, just needed to add your event listener to 'input' as i think then every keystroke the data in local storage is being updated.
Page 1
HTML
<textarea id="retro" class="form-control item"></textarea>
<button type="button" class="btn btn-primary" name="name">Send</button>
JS (I would recommend place this at the bottom of you page for quick testing)
<script type="text/javascript">
var textarea = document.getElementById('retro');
textarea.addEventListener('input',function(){
localStorage.setItem('retro', this.value);
})
</script>
In Chrome developer tools if you watch the variable 'localstorage' then you will see this change as you key in the value.
What I have done here is bound the event listener to the text area so that any 'input' the value changes, furthermore is am setting the item in the localstorage
PAGE 2
HTML
<textarea id="retro" style="height: 200px; width: 800px"></textarea>
JS
<script type="text/javascript">
var textarea = document.getElementById('retro').value = localStorage.getItem('retro');
</script>
Here using the 'getItem' method for localstorage you can then retrieve it from the storage area and output it as the value of the textarea.
Obviously is the cache or localstorage is cleared then this value will disappear.
PART 2 - Decoding Parameters in the URL and assigning them
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^]*)').exec(window.location.href);
if (results==null){
return null;
}
else{
return results[1] || 0;
}
}
This function above will get you any parameter you want form the url I found this from here. This is using jQuery.
Here is how you would use it
// example.com?param1=name¶m2=&id=6
$.urlParam('param1'); // name
$.urlParam('id'); // 6
$.urlParam('param2'); // null
Well I hope this answers your question on both parts, and helps you further, please add any comments if I have missed anything and I will be happy to update my answer
DISCLAIMER: total beginner with regards to browser extensions and javascript.
BACKGROUND:
I'm trying to develop a proof-of-concept Chrome extension that picks up the text from the input fields in the HTML form of the web page loaded into one tab, and enters the same text on analogous fields of the page in another tab.
In my particular example, the source page is a minimal, local HTML file with two input fields ("user name" and "password"), and the destination is the login page for Apple's Developer Website (https://developer.apple.com/account/).
Reading the official guides and questions here, I've put together some code that seems to work.
THE PROBLEM:
Only text consisting of digits (e.g.: "111111") gets copied from one tab to the other. As soon as my input field contains letters (e.g.: "111111a"), nothing happens.
This is the source page (local file:///):
<html>
<head>
<title>Source Page</title>
<meta charset="utf-8" />
<script src="popup.js"></script>
</head>
<body>
<form>
<input id="accountname_src" name="appleId" placeholder="Apple ID" /><br />
<input id="accountpassword_src" name="password" placeholder="Password" />
</form>
</body>
</html>
The destination HTML (Apple's page) has similar input fields with element ids of accountname and accountpassword, respectively.
My extension's script is as follows:
document.addEventListener('DOMContentLoaded', function(){
// The button in the browser action popup:
var button = document.getElementById('autofill');
var sourceTabID = null;
var destTabID = null;
// Get the SOURCE tab id:
chrome.tabs.query({'title': 'Source Page'}, function(tabArray){
sourceTabID = tabArray[0].id;
});
// Get the DESTINATION tab id:
chrome.tabs.query({'title': 'Sign in with your Apple ID - Apple Developer'}, function(tabArray){
destTabID = tabArray[0].id;
});
if (button !== null){
button.addEventListener('click', function(){
// Get entered text from Source page:
chrome.tabs.executeScript(sourceTabID, {file: "read_input.js"}, function(results){
var credentials = results[0];
var userName = String(credentials[0]);
var password = String(credentials[1]);
// Pass values to Apple login page:
var insertUserNameCode = "document.getElementById('accountname').value = " + userName + ";"
var insertPasswordCode = "document.getElementById('accountpassword').value = " + password + ";"
var autofillCode = insertUserNameCode + insertPasswordCode;
chrome.tabs.executeScript(destTabID, {code:autofillCode});
});
//window.close();
});
}
});
of course, the contents of read_input.js are:
var userName = document.getElementById("accountname_src").value;
var password = document.getElementById("accountpassword_src").value;
var attributes = [userName, password];
attributes // (Final expression, passed to callback of executeScript() as 'results')
It feels like there could be a type inference problem somewhere, but can't tell where.
Bonus Question:
I can read the input fields in the source page using an external script (read_input.js above) and the method chrome.tabs.executeScript(..., file:...; but when I try to write the values to the destination tab using a similar approach, the script does not run (that is why I'm using chrome.tabs.executeScript(..., code:... in my code). Any idea what can be happening?
Silly me (again)... Some console.logging led me in the right direction...
I was not escaping the value in the script; these lines:
var insertUserNameCode = "document.getElementById('accountname').value = " + userName + ";"
var insertPasswordCode = "document.getElementById('accountpassword').value = " + password + ";"
...should be:
var insertUserNameCode = "document.getElementById('accountname').value = '" + userName + "';"
var insertPasswordCode = "document.getElementById('accountpassword').value = '" + password + "';"
(added single ticks around the values)
...so that the code ends up as:
document.getElementById('accountname').value = '111111a';
...instead of:
document.getElementById('accountname').value = 111111a;
Still not sure why a numbers-only value works, though.
Maybe a chicken/egg problem.
Based on this answer: https://stackoverflow.com/a/27190520/1438215
I want to use javascript to populate the value of an asp.net hidden field (as soon as it's possible), and then access the value of that populated field in the server-side Page_Load event.
Sample:
aspx portion:
<div id="div_BrowserWindowName" style="visibility:hidden;">
<input type="hidden" name="ctl00$ctl00$BodyContent$MainContent$hf_BrowserWindowName" id="BodyContent_MainContent_hf_BrowserWindowName" />
</div>
<script type="text/javascript">
function PopBrowserWindowName() {
if (typeof window.name != undefined) {
if (window.name == '') {
var d = new Date();
window.name = '_myWnd_' + d.getUTCHours() + d.getUTCMinutes() + d.getUTCSeconds() + d.getUTCMilliseconds();
}
var eDiv = document.getElementById('div_BrowserWindowName');
var e = eDiv.getElementsByTagName('input')[0];
e.value = window.name;
alert(e.value);
}
}
window.onload = PopBrowserWindowName();
</script>
aspx.cs portion (page_load) event:
if (hf_BrowserWindowName != null)
{string winID = hf_BrowserWindowName.Value;}
This does works during postbacks, but does not work on the page's initial load.
Prior to Page_Load, there is no HTML or JavaScript because the Response has not been sent to the client yet. You need to learn the ASP.NET Page Lifecycle.
You can use server side code to populate the information, or after the page is sent to the client you can have some JavaScript populate the information.
I am trying to follow this example to show progress bar without using ajax to download file.
I use knockout,html and webapi. I am having below code which calls href on click event of button
this.getMeData= function () {
uRlPath("/api/GetSomeData?id=" + 12)
+ "&name=" + getName.toString()
+ "&downloadtoken=" + new Date().getTime());
$('#myLink').click();
location.href = $('#myLink').attr('href');
};
This is my html
<tr>
<td class="labelText">
<button data-bind="click: getMeData">
Download Data
</button>
</td>
</tr>
<tr>
<td>
<a id="myLink" data-bind="attr: { href: uRlPath }" style="visibility: hidden">Open </a>
</td>
</tr>
I now want to call some function on click event of my href
This is my webapi method which returns me cookie and binary file
public HttpResponseMessage GetSomeData(int id, string name, string downloadtoken)
{
var returnData= new HttpResponseMessage(HttpStatusCode.OK);
returnData.Content = new ByteArrayContent(mybyteArray);
var cookie = new CookieHeaderValue("downloadtoken", downloadtoken);
returnData.Headers.AddCookies(new CookieHeaderValue[] { cookie });
returnData.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
returnData.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
returnData.Content.Headers.ContentDisposition.FileName = "myfile.pdf";
return returnData;
}
To be very precise i want to have same behaviour as provided in example. In example they use form to submit but i dont have any form as i just use html,knockout. I have included all libraries mentioned in example.
Do let me know if you need more inputs.
I found solution myself. I used below code to check constantly for cookie
var attempts = 30;
var checkTime
startProgressBar(true)
checkTime= window.setInterval(function () {
var cookieValue = $.cookie('downloadtoken');
if ((cookieValue == token) || (attempts == 0)){
stopDownload();
}
attempts --;
}, 1000);
In finishDownload function i clear cookie and stop progress bar
function stopDownload() {
window.clearInterval(checkTime);
$.cookie('downloadtoken', null); //clears this cookie value
stopProgressBar(false);
}
This is html code for progress bar
<div data-bind="visible: stopProgressBar" style="top:248px;left: 320px;">
<img src="../images/ProgressBar.jpg" />
</div>
If you just want to call the blockUIForDownload function when the link is clicked, you can do it with a "click" binding, just like you did for the button:
<a id="myLink" data-bind="attr: {href: uRlPath}, click: blockUIForDownload" style="visibility: hidden">Open</a>
(This assumes the function is already defined within the viewModel.)
See official documentation for the "click" binding here: http://knockoutjs.com/documentation/click-binding.html
However, it looks to me like you're overcomplicating it a bit - in the example you posted, a hidden input field is required because they're using a form input as a means to transfer the token to the server.
In your case the token is passed as a part of an href attribute, so you can greatly simplify the code:
1) Remove the invisible link completely
2) Replace the getMeData function with the following:
this.getMeData= function () {
window.open("/api/GetSomeData?id=" + 12
+ "&name=" + getName.toString()
+ "&downloadtoken=" + new Date().getTime());
blockUIForDownload();
};
Can someone please tell me how to delay the resetting of a div background-image until a file upload has completed? All the parts individually work, however
I have to delay the setting of the background by having an alert pop up and then leave a while before clicking ok - I can't have since a user will not know how long to leave before pressing...
Any help appreciated though I should say that I briefly looked at jquery/ajax but found that it would only work in IE once before requiing a page refresh
Html...
<iframe id="MyFrame" name="MyFrame" style="display:none;"></iframe>
<form id="browseform" method="post" action="disp_photosave.asp" enctype="multipart/form-data" target="MyFrame">
<p>Please select your photo...</p>
<img src="Images/button_browse.gif">
<input type="hidden" name="tab" value="0">
<input type="file" id="upload" name="filesent" onchange="this.form.submit(); load_bk_photo()">
<input type="hidden" name="tempid" value="<%=(TId)%>">
<input type="hidden" name="side" value="<%=(strSide)%>">
<input type="hidden" name="varid" value="<%=(Request.querystring("varid"))%>">
<input type="hidden" name="prodid" value="<%=(Request.querystring("prodid"))%>">
</form>
javascript...
function load_bk_photo(){
var activeId = '<%=(activeTempStoreId)%>'
var redStr_id = "side1"
d = new Date();
time_temp = d.getTime();
photoUrl = "photos/merged_"+activeId+"_"+redStr_id+".png?"+d.getTime()
alert ("timebbb = "+time_temp )
$('#resizable-img').css('background-image','url("' + photoUrl + '")');
$('#resizable-img').css('display','block');
}
vbscript on disp_photosave.asp...
<%
Set Upload = Server.CreateObject("csASPUpload.Process")
Set Image = Server.CreateObject("csImageFile.Manage")
prodid = prodSet.Fields.Item("id").Value
redStr = "side1"
fieldPrefix = "front_"
If Upload.FileQty > 0 Then
Image.ReadVariant Upload.FileData(0)
Image.WriteFile Server.MapPath("this works ok"
Image.ResizeFit scale_width, scale_height
Image.WriteFile Server.MapPath("this works ok"
storeHeight = Image.Height
storeWidth = Image.Width
Set MyConn=Server.CreateObject("ADODB.Connection")
MyConn.Open "dsn=xxx;uid=xxx;password=xxx;"
SQLString = "this works ok"
MyConn.Execute(SQLString)
MyConn.Close
Set MyConn = Nothing
End if
%>
I also need to return the value storeHeight and storeWidth to the main page to use later so if anyone can advise me on that too.
Thanks in advance for any help.
Your load_bk_photo function has some issues (missing semi-colons, creating global variables), try changing to this:
function load_bk_photo(){
//we can use the `var` keyword once and separate each variable declaration by a comma, then finish all the declarations with a semi-colon
var activeId = '<%=(activeTempStoreId)%>',
redStr_id = "side1",
d = new Date(),
time_temp = d.getTime(),
photoUrl = "photos/merged_" + activeId + "_" + redStr_id+".png?" + time_temp;
alert ("timebbb = " + time_temp );
//you can use one `.css()` function call to do both operations
$('#resizable-img').css({
'background-image' : 'url("' + photoUrl + '")',
display : 'block'
});
}
You were creating global variables which is only necessary if you are changing the value of variables outside the scope of this function.
Onto your main question, you can set a load event handler for the <iframe> element as a callback function on your upload:
$('#MyFrame').on('load', function () {
//The iframe has loaded and you can do what you want, including get the contents of the iframe (server-response)
var response = $(this).contents().find('body').text();
});
Make sure to set this binding before the source of the <iframe> is changed.
Note that .on() is new in jQuery 1.7 and in this case is the same as .bind().
.on(): http://api.jquery.com/on
UPDATE
I don't know asp classic but if you output something like storeWidth|storeHeight in your asp code then you can get that response in you JavaScript and do what you want with it:
$('#MyFrame').on('load', function () {
//The iframe has loaded and you can do what you want, including get the contents of the iframe (server-response)
var response = $(this).contents().find('body').text().split('|');
alert(response[0] + 'x' + response[1] + 'px');
});
I would use a global callback method:
JavaScript:
window.uploadComplete = function (returnData) {
$('#resizable-img').css('background-image','url("' + returnData.photoUrl + '")');
$('#resizable-img').css('display','block');
alert(returnData.storeHeight + "|" + returnData.storeWidth);
}
And in ASP, return this to the iFrame:
<script>
parent.uploadComplete({photoUrl: "urltophoto",storeHeight: "<value from asp var>", storeWidth: "<value from asp var>"});
</script>