Making sense of RegisterStartupScript: How often will the JavaScript code be called? - javascript

The documentation of ScriptManager.RegisterStartupScript says (emphasis mine):
Registers a startup script block for every asynchronous postback with the ScriptManager control and adds the script block to the page.
[...]
Remarks
You use this method to register a startup script block that is included every time that an asynchronous postback occurs. [...]
Thus, I would have expected that once I register a script block with RegisterStartupScript, it is executed on every subsequent async postback. However, this is not what happens. Here is a MCVE:
<%# Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void btnRegisterScript_Click(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "Test script",
"window.alert('Script triggered!');", true);
}
protected void btnRegularPostback_Click(object sender, EventArgs e)
{
// Do nothing
}
</script>
<html>
<head>
<title></title>
</head>
<body>
<form runat="server">
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Button ID="btnRegisterScript" Text="Register Script" runat="server" OnClick="btnRegisterScript_Click" />
<asp:Button ID="btnRegularPostback" Text="Regular Postback" runat="server" OnClick="btnRegularPostback_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Repro:
Click on "Register Script".
Click on "Regular Postback".
Expected result:
Both step 1 and step 2 cause a JavaScript alert (because step 1 registered the script and step 2 is an async postback).
Actual result:
Only step 1 causes a JavaScript alert.
This is fine for me. I want the alert only to occur during step 1 (and not step 2). However, the behavior does not match the documentation and, thus, I want to know the reason for my misunderstanding.

I just tried out the scenario you described and this is what i observed:
On every click of "Register Script" button, one <script type="text/javascript">window.alert('Script triggered!');</script> tag gets added as child of the 'head' tag. So if you do 3 clicks, you will get 3 script tags under the head tag.
I believe this is what the documentation says about every asynchronous postback.
On clicking the "Regular Postback" button, there is no way for the already registered script(registered by "Register Script") in the 'head' tag to execute. And there is no script that is registered in the event handler of this button. So i don't expect the script to get executed in "Regular Postback" button click.

Related

Adding ASP.Net tags from javascript, why does this work?

I got an ASPX page with the folowing code behind
public partial class test : Page
{
protected void test(object sender, EventArgs e)
{
throw new Exception("test");
}
}
And the following ASPX code:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="test.aspx.cs" Inherits="test" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Thumbnail</title>
</head>
<body>
<form id="form1" runat="server">
<div id="buttonTarget">
</div>
</form>
</body>
</html>
If I run the following javascript a button is added to the page:
$('#buttonTarget').html('<asp:Button runat="server" ID="tst" CssClass="buttons" OnClick="Test" Text="Test"/>');
The buttons shows the same way as an asp tag shows in element inspector.
And when I click the button the server sided function is called and the site breaks with the "test" exception
I know this isn't good practice but I want to know why this works. Why does this button call the server sided function and why is it displayed as a normal button ?
--EDIT--
The aspx code was a simplified version. The actual code used a gridview control and used javascript to insert rows in the table. These rows hold the tags.
Expanding on what #Mamun was probably saying, when the page is executing on the server, it's seeing the asp tag in the JS string and translating it into the appropriate HTML. If you view source on your page in the browser, you'll probably see something like this instead of the ASP tag in your JS call:
$('#buttonTarget').html('<input type="submit" name="ctl00$MainContent$tst" value="Test" id="MainContent_tst" class="buttons" />');

How do I put javascript programmatically into <head> block?

I need to put some javascript absolutely in the <head> block of the page -- it must execute before the rest of the page because a possible outcome of the script is to redirect to a different page.
However, when I use RegisterClientScriptInclude (to put some jQuery in there) and RegisterClientScriptBlock for my code which uses the jQuery, it puts it near the top of the <body> block, and it does not execute. I can't see a way to programmatically put this javascript into the <head> block -- it must be programmatically because sometimes I don't want it there, and sometimes I do.
I've tried to see if I can directly reference Content1, the ID of the asp:Content element corresponding to the <head> block, but no go.
Just in case anyone thinks that RegisterStartupScript might work: it doesn't. It puts it lower in the <body> block than everything else. Oddly enough.
Want some code? Here:
Type csType = this.GetType();
ClientScriptManager clientScript = Page.ClientScript;
if (!clientScript.IsClientScriptIncludeRegistered(jqueryScriptName))
{
clientScript.RegisterClientScriptInclude(jqueryScriptName, "~/Scripts/jquery-1.7.1.min.js");
}
if (!clientScript.IsClientScriptBlockRegistered(citrixDetectorScriptName))
{
clientScript.RegisterClientScriptBlock(csType, citrixDetectorScriptName, citrixDetectorScriptText, true);
}
By popular demand, how I detect the ActiveX component. This is JScript.
try {
var icaObj = new ActiveXObject("Citrix.ICAClient");
var CitrixVersion = icaObj.ClientVersion.split(".");
var MajorMinorVersion = CitrixVersion[0] + "." + CitrixVersion[1];
if (MajorMinorVersion == "11.0") {
// Citrix is OK
}
else {
window.navigate("WrongCitrix.aspx?Citrix=" + MajorMinorVersion);
}
}
catch (e) {
window.navigate("NoCitrix.aspx");
}
If the ActiveX component is not present, then redirection is a page that tells the user they need to install it. If the ActiveX component is any other version than 11.0, then the redirect is to a page that explains this and how to deal with the situation (backrevving for example).
An prior check during page load checks to make sure they have Internet Explorer v4 thru v9, because any other version will not work with the product (and IE10+ will crash if it even tries to load v11.0 of the ActiveX component).
If I understand your question, you can insert PlaceHolder control wherever you want inside the page.
<%# Page Language="C#" AutoEventWireup="True"
CodeBehind="Default.aspx.cs" Inherits="WebApplicationTelerik.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript"
src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
protected void Page_Load(object sender, EventArgs e)
{
PlaceHolder1.Controls.Add(new LiteralControl(
"<script type=\"text/javascript\"> alert('here'); </script>"));
}
document.GetElementsByTagName("head")[0].appendChild( newScriptNode );
or jQuery
$("head")[0].append( newScriptNode );
If you really must insert JavaScript into the head tag, you can just make it an ASP.NET control and insert a control into it's child collection.
E.g. In the ASPX file:
<head runat="server" id="header">...</head>
In the code behind:
header.Controls.Add(new Literal("<script type='text/javascript'>...</script>"));
Although I do think you need to think about your process, it would be more efficient to redirect the user in the back-end before the page is rendered.
Oh and RegisterStartupScript correctly places your JavaScript after your html for increased load performance.

Call a function defined in an external javascript function from vb.net code behind (.html not .aspx)

I have a plain .html page which has a hiddenField and a reference to External.js. Since I am implementing using ASP.NET, server side will execute first. However, I need to execute a function in External.js before server code execution. The solution is available by the having the following code:
*In .aspx *
<script src="External.js" type="text/javascript"></script>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />`
In .aspx.vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
If Not Page.IsPostBack Then
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "register", "MyFunction();", True)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
The code works perfectly when I am using a .aspx page. Obviously, I cannot use any ASP.NET server controls in a plain .html page. So using <asp:ScriptManager> in a .html page will not work. How can I do the same exact thing but in an .html page. What should be defined in the .html page and how can I call the function from the code behind, keeping in mind that I cannot use any <asp:> controls.
Ok so what I am trying to do is that I have my External.js which has the function populateHidden() which basically sets a value to my hiddenField.
function populateHidden()
{
document.getElementByID('Hidden').value = "abcdefg";
}
I also have another function PassData() which basically initializes an ajax request to the server to pass the value of Hidden to the code behind (using a webMethod). The problem is that I want populateHidden() to execute first so that passData() passes abcdefg (after populateHidden() is executed) to the code behind to store the value in a database. So currently the way I am running both functions is as follows.
in .html
<body onload="PassData()">
in code-behind
trying to execute populateHidden(); on Page_Load since server side executes first.
I borrowed this from #Cleydson's answer:
JS
function MyFunction()
{
populateHidden();
PassData();
}
HTML
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="External.js" type="text/javascript"></script>
</head>
<body onload="MyFunction();">
...
</body>
Now you're calling populateHidden() before PassData()
I’m not sure if I understood it correctly. But, if you want do call a script in the same way you’ve done you just need to do it:
<body onload="MyFunction();">
complete version:
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="External.js" type="text/javascript"></script>
</head>
<body onload="MyFunction();">
...
</body>
</html>
Is it?

How to call javascript function from code-behind

I wrote a javascript with a asp.net page.
In Asp.net Page
<HTML> <HEAD>
<script type="text/javascript">
function Myfunction(){
document.getElementId('MyText').value="hi";
}
</script>
</HEAD> <BODY>
<input type="text" id="MyText" runat="server" /> </BODY>
In Code-behind
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load
If Session("My")= "Hi" Then
I want to call "Myfunction" javascript function
End If
End Sub
How can I do?
One way of doing it is to use the ClientScriptManager:
Page.ClientScript.RegisterStartupScript(
GetType(),
"MyKey",
"Myfunction();",
true);
This is a way to invoke one or more JavaScript methods from the code behind.
By using Script Manager we can call the methods in sequence. Consider the below code for example.
ScriptManager.RegisterStartupScript(this, typeof(Page), "UpdateMsg",
"$(document).ready(function(){EnableControls();
alert('Overrides successfully Updated.');
DisableControls();});",
true);
In this first method EnableControls() is invoked.
Next the alert will be displayed.
Next the DisableControls() method will be invoked.
There is a very simple way in which you can do this. It involves injecting a javascript code to a label control from code behind. here is sample code:
<head runat="server">
<title>Calling javascript function from code behind example</title>
<script type="text/javascript">
function showDialogue() {
alert("this dialogue has been invoked through codebehind.");
}
</script>
</head>
..........
lblJavaScript.Text = "<script type='text/javascript'>showDialogue();</script>";
Check out the full code here: http://softmate-technologies.com/javascript-from-CodeBehind.htm (dead)
Link from Internet Archive: https://web.archive.org/web/20120608053720/http://softmate-technologies.com/javascript-from-CodeBehind.htm
If the order of the execution is not important and you need both some javascript AND some codebehind to be fired on an asp element, heres what you can do.
What you can take away from my example:
I have a div covering the ASP control that I want both javascript and codebehind to be ran from. The div's onClick method AND the calendar's OnSelectionChanged event both get fired this way.
In this example, i am using an ASP Calendar control, and im controlling it from both javascript and codebehind:
Front end code:
<div onclick="showHideModal();">
<asp:Calendar
OnSelectionChanged="DatepickerDateChange" ID="DatepickerCalendar" runat="server"
BorderWidth="1px" DayNameFormat="Shortest" Font-Names="Verdana"
Font-Size="8pt" ShowGridLines="true" BackColor="#B8C9E1" BorderColor="#003E51" Width="100%">
<OtherMonthDayStyle ForeColor="#6C5D34"> </OtherMonthDayStyle>
<DayHeaderStyle ForeColor="black" BackColor="#D19000"> </DayHeaderStyle>
<TitleStyle BackColor="#B8C9E1" ForeColor="Black"> </TitleStyle>
<DayStyle BackColor="White"> </DayStyle>
<SelectedDayStyle BackColor="#003E51" Font-Bold="True"> </SelectedDayStyle>
</asp:Calendar>
</div>
Codebehind:
protected void DatepickerDateChange(object sender, EventArgs e)
{
if (toFromPicked.Value == "MainContent_fromDate")
{
fromDate.Text = DatepickerCalendar.SelectedDate.ToShortDateString();
}
else
{
toDate.Text = DatepickerCalendar.SelectedDate.ToShortDateString();
}
}
asp:run javascript method
Add this line to the bottom of the page before </form> tag, at least under the js function you wrote.
the reason of doning this is avoid calling your method before your
browse knowing what is the funcion and finally do nothing.
<% Response.Write($"<script>yourfunction('{Config.id}');</script>"); %>
ps: I've tried all methods up there but nothing worked fine for me. And I figure out this easy and wonder way of calling js method on my own!

jQuery function before the Postback for FileUpload in ASP.NET

So, I have an .aspx webpage as follows:
..
<form id="frm" runat="server">
<asp:FileUpload runat="server" id="fileupload" onchange="browsed()" />
<asp:Button runat="server" OnClick="Upload_Click" id="uploadbutton" class="uploadbutton" Text="start upload" Enabled="false" />
<div id="nfo" style="display: none">
blabla
</div>
</form>
..
Now, as you can guess correctly, user chooses file to upload, clicks #uploadbutton and, voila, Upload_Click is called after the postback.
Then, I want to show div #nfo with some jQuery effects during the upload. To do this, I write:
$(function() {
$('.uploadbutton').click(function() {
$('#nfo').slideDown().show("fast");
})
})
and everything works just fine, until the user starts browsing in IE...
First of all, in IE, user has to click #uploadbutton twice - first time to display #nfo, second time, for some reason, to initiate postback.
Secondly, after the postback, Upload_Click's this.fileupload.HasFile shows false.
FF and Chrome works quite well though.
As far, as I can understand this - in IE jQuery's function prevents something important for asp:FileUpload from happening and stops the postback. Though, on the second click it does initiate the postback, but still with no info for asp:FileUpload's Upload_Click.
Any help?
Update:
followed #joelt'd advice. turned out, there was some different problem, never thought it could be of importance, so I didn't provide source code for that part =(
see localizing <asp:FileUpload>. IE problem
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#Button1").click(function() {
$("#progress").show();
});
});
</script>
</head>
<body>
<form runat="server">
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" />
<div id="progress" style="display:none; background-color:Red;">test</div>
</form>
</body>
</html>
This works fine for me in FF and IE7, except in IE, the progress indicator doesn't really give you anything because of how it's rendering, I suppose. I would say the biggest difference between our code is the "onchange=browsed()" function. It's possible that's not getting called until you click the button? In any case, I would start with a stripped down page like this, and start adding in other elements you have until it breaks.
try this:
<asp:Button runat="server" OnClick="Upload_Click" id="uploadbutton"
class="uploadbutton" Text="start upload" Enabled="false"
OnClientClick="return myFunction();"/>
<script type="text/javascript">
function myFunction(){
$('#nfo').slideDown().show("fast");
return true;//THIS WILL FIRE POSTBACK EVENT
//return false;//THIS WILL STOP POSTBACK EVENT, WHICH YOU MAY WANT IF THERE
//IS NO FILE SELECTED
}
</script>

Categories

Resources