I have some links in an UpdatePanel. For example:
Products
I also have a CSS rule that puts an icon next to off-site links (those that have an HREF that starts with "http"):
a[href^="http"]
{
padding-right: 18px;
background: transparent url("Icons/offsiteLink.png") no-repeat right bottom;
}
When the page loads initailly, the links correctly do not have the off-site icon. The problem is that after an Ajax postback using the UpdatePanel, the icon appears next to the links! I added a hover event to display the href attribute, and it has indeed been changed to have the full path to the page after the Ajax postback. It doesn't matter if the links are plain HTML tags or a TreeView node.
Is this an issue with ASP.NET, or Ajax in general? Can I stop it?
Thanks.
Update:
I have created a brand new Web Site project. This is in Visual Studio 2008/.NET 3.5. Here is the entirety of the code:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" 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>Test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="mainScriptManager" runat="server" />
<asp:UpdatePanel ID="updatePanel1" runat="server">
<ContentTemplate>
<p><a id="internalLink" href="About.aspx"
onmouseover="$('#hrefValue').text($(this).attr('href'));">About</a></p>
<p><a id="offsiteLink" href="http://example.com/"
onmouseover="$('#hrefValue').text($(this).attr('href'));">Offsite</a></p>
<p>HREF: <span id="hrefValue"></span></p>
<asp:Button ID="submitButton" Text="Post Back" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
(The code behind is empty.)
When I load the page in IE 7 and hover the links, I get:
About.aspx
http://example.com/
Then, I click the button, and hover the links again. This time they are:
http://localhost:4069/TestSite/About.aspx
http://example.com/
Notice that the first one changed to the full path.
Instead of looking for "http", you could add a rel="external" attribute to external site links, then style them using:
a[rel=external] {
}
See CSS - style a link based on its "rel" attribute?
It turns out that this was caused by an issue with IE7. IE8 no longer has the issue.
Due to several factors, I decided to use JavaScript to fix it. Here is that code. I also included a snarky comment about my company still targeting IE7 ;)
company.offsiteIconFix = (function() {
function init() {
var i, allAnchors = document.getElementsByTagName("a");
for (i = 0; i < allAnchors.length; i++) {
if (allAnchors[i].hostname && allAnchors[i].hostname ===
location.hostname) {
var trimIndex = allAnchors[i].href.indexOf(allAnchors[i].host) +
allAnchors[i].host.length;
var trimmedUrl = allAnchors[i].href.substring(trimIndex);
allAnchors[i].setAttribute("href", trimmedUrl);
}
}
}
return {
init: init
};
})();
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(company.offsiteIconFix.init);
I could change it to insert "rel=external" as suggested by mgnoonan.
Related
I have a class that modifies the path of a resource (e.g., a stylesheet) based on that file's last modified time. This is in order to prevent caching of stale resources.
The class works on all "normal" pages, but I can't get it to work in a local ASP.NET page that's rendered inside of an iframe. The class is located in ~/App_Code:
fingerprint.aspx.cs
public class Fingerprint {
public static string Tag(string rootRelativePath) {
if (HttpRuntime.Cache[rootRelativePath] == null) {
string absolute = HostingEnvironment.MapPath(rootRelativePath);
DateTime date = File.GetLastWriteTime(absolute);
int index = rootRelativePath.LastIndexOf('/');
string result = rootRelativePath.Insert(index, "/v-" + date.Ticks);
HttpRuntime.Cache.Insert(rootRelativePath, result, new CacheDependency(absolute));
}
return HttpRuntime.Cache[rootRelativePath] as string;
}
}
And in under most circumstances, it works successfully if called as follows:
somepage.aspx
<%# Page Language="C#" AutoEventWireup="true" Inherits="MainSite" CodeFile="somepage.aspx.cs" %>
<html>
<head runat="server">
<title>Title</title>
<link rel="stylesheet" href="<%# Fingerprint.Tag("/path/to/resource.css") %>">
<!-- other markup -->
</head>
<body>
<!-- other markup -->
</body>
</html>
But if I have an ASP.NET page that loads another ASP.NET page inside an iframe, it doesn't seem to get called. Example:
parent.aspx
<%# Page Language="C#" AutoEventWireup="true" Inherits="MainSite" CodeFile="parent.aspx.cs" %>
<asp:Panel ID="Container" runat="server">
<iframe id="testFrame" src="child.aspx"></iframe>
</asp:Panel>
child.aspx
<%# Page Language="C#" AutoEventWireup="true" Inherits="MainSite" CodeFile="child.aspx.cs" %>
<html>
<head runat="server">
<title>Title</title>
<link rel="stylesheet" href="<%# Fingerprint.Tag("/path/to/resource.css") %>">
<!-- other markup -->
</head>
<body>
<!-- other markup -->
</body>
</html>
I don't get any errors, but Fingerprint.Tag doesn't seem to even be getting called. I just get an empty string in the href portion of the <link> tag where the path to my stylesheet would normally be.
Is there a trick to getting server tags to work inside of local ASP.NET pages contained in iframes? I'm using ASP.NET WebForms (no other choice, client requirement).
What about changing <%# Fingerprint.Tag("/path/to/resource.css") %> to <%=Fingerprint.Tag("/path/to/resource.css") %>? Changing # to =.
As far as I know, <%# ... %> is more like a data binding syntax.
I'm trying to reset my form using javascript on client side. The code looks like this:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<!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" >
function Reset() {
TextBox1.text = "";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="Reset()" />
</div>
</form>
</body>
</html>
This of course isn't working, I get the error that Button1 is undefinded. I tried looking control's name within browser (by viewing page source) and using that instead of its ID but that didn't work either.
you need to get the value using getElementById
var mybutton= document.getElementById('Button1');
mybutton.value = ""
I advise you to use jQuery for your javascript code. It's a standard anyway.
After you reference jQuery, you may rewrite your JavaScript as follows:
<script type="text/javascript" >
function resetForm() {
$("#<%=TextBox1.ClientID %>").val("");
}
</script>
If you still do not want to use jQuery, then you need to access your element using its client ID like following:
<script type="text/javascript" >
function resetForm() {
document.getElemenyById("<%=TextBox1.ClientID %>").value = "";
}
</script>
Also, as #Jon pointed out, you need to either rename your OnClientClick value to resetForm() or rename your JavaScript function.
Here's what I have so far but thing aren't really working. (I dragged the jQuery.js file from the Solution Explorer to the area of my html.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SignUpFormTest._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 src="Scripts/jquery-1.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
//fade in the context of whatever is inside the div tag.
$('#name').fadeIn("slow");
});
</script>
</head>
<body bgcolor="#FFFFFF">
<p>
Note that this form doesn't actually do anything
except illustrate the Required Field Validator.
</p>
<form id="frmValidator" action="required.aspx" method="post" runat="server">
Enter Your Name:
<asp:TextBox id="txtName" runat="server" />
<div id="name"><asp:RequiredFieldValidator id="valTxtName" ControlToValidate="txtName" ErrorMessage='<img src="../Images/no.png">' runat="server" /></div>
<br />
<asp:button id="btnSubmit" text="Submit" runat="server" />
</form>
<p>
Hint: Try submitting it before you enter something.
</p>
</body>
</html>
When validating the icon just pops up.
No fade in or anything. Also, I know my current solution is hacky, so I'd really like someone to tell me what I should do instead of a creating a DIV tag just for the purpose of one animation.
Make sure the reference to JQuery is valid and use this code:
$(document).ready(function() {
$('#name').hide().fadeIn("slow");
});
If I'm not mistaken, since the div is already visible in your case, jQuery will not fade it in. The hide() method ensures that the div is initially not visible and then fades in slowly.
$(document).ready(function() {
document.getElementById('valTxtName').onpropertychange = function(){
$('#name').fadeIn("slow");
}
});
I have a parent page with two data controls. I want to be able to open a child window, do something on it, and when it closes I want to rebind only one of the two data controls on the parent page. I have the control I want to update within an UpdatePanel so would like to call rebind it and call UpdatePanel.Update().
From a child window, you can't actually "call" a server side function for the parent page, however you can use some javascript to invoke client side functions on that page.
On the parent page:
<script language="Javascript" type="text/javascript">
function CallAlert()
{
alert("This is parent window's alert function.");
}
</script>
On the child page:
<script language="Javascript" type="text/javascript">
function CallParentWindowAlert()
{
window.opener.CallAlert();
return false;
}
</script>
In the example you provided, in particular where you have an UpdatePanel, you've actually left yourself a few options here. If the UpdatePanel is set with some form of trigger to force it to update, be it all children or just specified ones, in your parent function you can force a postback on one of those controls. Ultimately, the parent pages javascript function should have some form of a __doPostBack() call, referencing the id of a control and some (empty) parameter, however you'd probably be better off generating that javascript with codebehind via:
Page.ClientScript.GetPostBackEventReference(control, null);
Once you put that together, it's all a matter of tying the actual invocation to whatever client side event you want on your child page, be it onUnLoad() or in some custom function you call.
Try this out all you got to do is call __doPostBack on the parent page targeting the update panel or something in the update panel.
Parent Code:
<%# Page Language="C#" %>
<!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>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Parent Window</h1>
Time:
<%= DateTime.Now.ToString() %>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
Update Panel Time<%= DateTime.Now.ToString() %>
<br />
<asp:Button ID="Button1" Text="Submit" runat="server" />
Click To Open Child Window
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Child Code:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript" language="javascript">
function UnloadMe() {
if (opener) {
opener.__doPostBack("UpdatePanel1", "");
}
}
</script>
</head>
<body onunload="UnloadMe()">
<form id="form1" runat="server">
<div>
<h1>Child Window</h1>
</div>
</form>
</body>
</html>
I keep getting these requests for 'make me a tool to do xyz' for a web app we're putting up.
So after the third one, I realized it'd be easier to lump them all together and use a master page.
I've got a user control called MessageCenter I use for error, success, and informational messages, and so I dropped that on the master page.
<%# Master Language="VB" CodeFile="tfMasterPage.master.vb" Inherits="tfMasterPage" %>
<%# Register Src="MessageCenter/msgCenter.ascx" TagName="msgCenter" TagPrefix="uc1" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>INSERT TITLE HERE</title>
<link href="Stylesheets/EogTool.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/TF_Main_Styles.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/TF_Print_Styles.css" rel="stylesheet" type="text/css" media="print" />
</head>
<body style="background-color: #eeeeee">
<form id="form1" runat="server">
<div class="page">
<div class="headerArea">
<div class="LogoImg">
<img alt="Transparency Florida" src="images/TF_Logo.jpg" /></div>
<div class="SealImg">
<img alt="Shining the Light on Florida's Budget" src="images/TF_Seal.jpg" /></div>
</div>
<div class="content">
<h1>
FIS - EOG Table Maintenance</h1>
</div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div class="content">
<div>
<uc1:msgCenter ID="MsgCenter1" runat="server" />
</div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
...
Normally, when the msgcenter is on a regular aspx page, I call its method and stuff from the codebehind as in this sub:
...
rtn = dal.deleteRow(CInt(e.CommandArgument), currentTab())
If Not IsNumeric(rtn) Then
MsgCenter1.addMessage("An Error occured deletion" & rtn, , , , "E")
Else
MsgCenter1.addMessage("Delete Successful", , , , "S")
End If
bindGrid()
MsgCenter1.Visible = True
End Sub
But when I try to do that from the asp:content thing on the page using the masterpage, it tells me that msgCenter1 is not declared. It's some sort of scope issue.
I've read about using findcontrol like
ctype(master.findcontrol("tbWhatever"), textbox).text = "FOO"
But when I try to cast to my user control, it complains because it once again, isn't declared.
I feel as though I'm just missing one piece of the puzzle, but it's been eluding me since around 4PM yesterday.
Any advice, pointers, or links would be most appreciated.
Thanks.
First add this directive to the content page you want to access the master page
<%# MasterType VirtualPath="~/NameOfMasterPage.master"%>
Second, On the master page setup a public propery that returns the control you want to access
public Label MasterLabel
{
get
{
return lblMaster;
}
private set
{
//do nothing
}
}
Lastly just access the control in the content page like so
Master.MasterLabel.Text = "Hello from the content page!";
I know your question has been answered and this doesn't apply to it, but I noticed you're passing in 1 length characters for your "MessageCenter" control. I would use an Enum instead of a string to make your code a little less brittle. As it stands now you can pass "fart" in as a parameter and it will compile just fine. An Enum will give you some compile time checking and avoid any issues at runtime.
Examples:
Message.Success
Message.Error
Message.Warning
this is what i'd been used.
Master.FindControl("ControlID").Visible = false;