Make Sectioned Page Content - javascript

This question is pretty difficult for me to phrase well, so please bear with me.
In VS Express I'm creating a series of web pages. On each page I want there to be a series of functions, relevant to a given user role. I want all my html code on a single aspx page, but with only certain sections appearing (hopefully asynchronously) as determined by the url which will be linked to via a drop down menu in the navbar.
I would like to use Rerouting (I think it's called) to keep my urls nice and more malleable so I can change them later without breaking bookmarks and such.
As a user, in a given role, I would mouse over the drop-down menu and see only the functions which I am allowed to perform. Upon clicking on one, it would update the url something like domain.com/form1 and would only show the block of code (in the aspx page, and again, preferably asynchronously) relevant to that action.
I'm thinking to use divs and the css "display:none;" property. I'm not not sure by what mechanism to toggle between the "views," if you will, of the various functions. Should I use Javascript of ASP.NET?
I'm so sorry for such a convoluted question. I spent over 20 minutes and this is the best way I could figure to ask. Does this even many any sense? If so, am I going about this all wrong or am I on the right track? I appreciate any stabs at this.
Cheers ;)
PLEASE READ: I originally wanted to accomplish this with the urls, but I found that using the "MultiView" ASP.NET control is was a much better solution to my dilemma. I just wanted to clear up any presumed discrepancy between my original question and my answer. Like I said, it was a difficult question to figure out how to ask at the time. :)

It's actually called URL rewriting. There is a few way to achieve that, the easier might be the wizard in IIS.
As for all your html in a single page, you could use panels and change their visibility when needed.

Being somewhat new to .NET and especially ASP.NET, I'm learning new things everyday, literally. I've recently discovered the "Multiview" control, which is amazing. I've used it for creating multiple menu bars (I know this seems wierd, but it's to simulate different user "modes" or user groups, etc), as well as the combining of content onto a single page as I mentioned in my original question. I then added a secondary control for toggling between the menus. Here is some sample code for how I implemented the control for my multi-menubar :P
<asp:MultiView ID="MenuView" runat="server">
<!-- ADMIN GROUP -->
<asp:View ID="View0" runat="server">
<asp:Menu ID="adminNav" runat="server" CssClass="menu" IncludeStyleBlock="False" Orientation="Horizontal"><DynamicMenuItemStyle />
<Items>
<asp:MenuItem NavigateUrl="~/Reports.aspx" Text="View Reports" />
<asp:MenuItem NavigateUrl="~/Approve.aspx" Text="Compliment hard-working employees" />
<asp:MenuItem NavigateUrl="~/Promote.aspx" Text="Promote the qualified employees :)" />
<asp:MenuItem NavigateUrl="~/Fire.aspx" Text="Send underlings home to starving children" />
</Items>
</asp:Menu>
</asp:View>
<asp:View ID="View1" runat="server">
<!-- USERS -->
<asp:Menu ID="userNav" runat="server" CssClass="menu" IncludeStyleBlock="False"
Orientation="Horizontal"><DynamicMenuItemStyle />
<Items>
<asp:MenuItem NavigateUrl="~/Work.aspx" Text="Look productive" />
<asp:MenuItem NavigateUrl="~/Complain.aspx" Text="Complain about boss" />
<asp:MenuItem NavigateUrl="~/Praise.aspx" Text="Show appreciation for your awesome boss" />
</Items>
</asp:Menu>
</asp:View>
</asp:MultiView>
<!-- MODE MENU -->
<asp:DropDownList ID="modeMenu" runat="server" AutoPostBack="True"
ViewStateMode="Inherit" CssClass="modeMenu" EnableViewState="True">
<asp:ListItem>Admin</asp:ListItem>
<asp:ListItem>User</asp:ListItem>
</asp:DropDownList>
Code Behind for controlling "MenuView" with "modeMenu" dropdown which I have as "position:fixed; left:5px; top:5px;" in my CSS to keep it out of the way.
Protected Sub mode(ByVal sender As Object, ByVal e As System.EventArgs) Handles modeMenu.Load, modeMenu.SelectedIndexChanged
Session.Add("mode", modeMenu.SelectedValue) //I use a session variable to maintain the state of the menu.
Select Case (modeMenu.SelectedValue)
Case "Admin"
MenuView.ActiveViewIndex = 0
Case "User"
MenuView.ActiveViewIndex = 1
End Select
End Sub
There you have it. I hope someone else finds this useful. Cheers ;)

Related

asp:GridView allow Edit button, but remove Update and Cancel buttons

This one is pretty straightforward. The asp:GridView automatically adds an Edit hyperlink to the left of every column like this:
which is fine because I need that functionality anyways. However, I've made it so clicking the Edit hyperlink brings up a new panel that allows the user to edit more properties than are shown in the GridView, so I don't want the Update and Cancel buttons to appear after clicking Edit.
Ive added the Edit functionality by implementing an event handler that Handles GridView.RowCommand when e.CommandName = "Edit". I would like to just keep the Edit hyperlink there, or maybe programatically click Cancel, or really anything that will keep the Update and Cancel hyperlinks from showing when the user finishes working with the Edit panel. I've tried calling the event handler and sending in args with e.CommandName = "Cancel" but that didn't work.
Another option I'm willing to explore is removing the Edit button entirely and making my event handler handle a different event, but I haven't found any good resources for that either. Mostly it's people trying to disable an Edit button that they've manually created on certain rows. I didn't create this Edit hyperlink, though, and I can't get it to go away.
Well, since you popping up a panel? Then just dump the whole template and auto editing system. Really, for quick and dirty - those built in GV events are great to get you up and running.
But, it turns out once you REALLY get the hang of how all this works? You can just pure code your way though this, and you even wind up with LESS code and LESS markup, and less hassle!!!
In fact, you can even dump the whole GV "row" handler - as it does not really again do you much of any favors here.
in fact, even better? Just drop in a plane jane edit button - even a asp.net one. You don't really need anything much more! - and you wind up often with even LESS confusing code. And REALLY great? Well, each button you add to the GV has its own click event - is it own nice button click with its own button click - quite much like any other control or button you just drop into the GV.
In fact, if the queston was how to tab around and edit the gv like Excel, I can post a really short, easy solution, and NONE of it uses the built in events of the GV.
but, lets outline how this can work, and work with a "min" of code.
You don't mention what kind of "dialog" you using here (and there are lot of them, ranging from jquery.UI (which I will use), or even the dialog from the ajaxtoolkit is also very nice.
So, I will say I do NOT like to suggest introduction of "just one more" JavaScript library. However, almost for sure, you have jQuery installed by default. So, adding jquery.UI is not all that big of deal.
So, our goals:
Dump the messy GV event model.
STILL use + write as much as possible easy server side code.
Write and use a absolute min of JavaScript code.
Now, I am going to use a few helper routines I wrote in vb.net. They are short, and easy to use. I became VERY fast tired of writing the same code over and over to:
Shuffle data from data table to some controls for edit
Shuffle data from controls back to table, and then save table to database.
However, even without the above "shuffle to/from" routines, you see that this code is MUCH less hassle by actually dumping the GV events.
Ok, So, lets assume a simple grid of hotels. And on each row, we want a edit button.
So, the first easy part, here is our grid:
<div style="width:40%">
<asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn" OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
A few FYI: Yes, to save time, I did use the wizards to create above. I then blow out the datasource1, and data source setting of the gv. and I removed the "ID" from display for each row. NOTE VERY careful - the PK row "id" setting is now this:
DataKeyNames="ID"
This is great feature, since it will maintain, use, and allow you to easy get the PK row id, but NOT have to expose it in the markup - less code, better to never show the PK stuff to users.
And note how I set CssClass="table". Don't worry about that, but doing so will bootstrap the GV - and it looks WAY WAY nicer. (and it also auto expands/grows to the div width size - do try this - since bootstrap is installed by default).
And now our code is this:
(don't worry - I'll include all code used here).
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
Dim cmdSQL As New SqlCommand("SELECT * FROM tblHotelsA ORDER BY HotelName")
GHotels.DataSource = MyrstP(cmdSQL)
GHotels.DataBind()
End Sub
and now we have this:
So far, really easy.
Now, it not clear what you used for editing (your popup), but we need "some kind" of popup system. So, I'll pick jquery.UI. It work rather well - far better then trying to get a bootstrap dialog to work.
So, after the GV, we need to layout + make a "one row" editor. (and place it in a div). so, this looks quite nice for this purpose: (and during development, I do NOT set display:none, but once you have it looking ok, then set display:none for the div style - that hides it (jquery.ui then takes care of this).
Ok, not too much to our "edit detals div". I dropped htis right after the GV.
So, we have this:
<div id="EditRecord" runat="server" style="float:left;display: none">
<style>
.iForm label {display:inline-block;width:90px}
.iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm input[type=checkbox] {margin-right:8px}
</style>
<div style="float:left" class="iForm">
<label>HotelName</label><asp:TextBox ID="txtHotel" runat="server" f="HOtelName" width="280"></asp:TextBox> <br />
<label>First Name</label><asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140"></asp:TextBox> <br />
<label>Last Name</label><asp:TextBox ID="tLN" runat="server" f="LastName" Width="140"></asp:TextBox> <br />
<label>City</label><asp:TextBox ID="tCity" runat="server" f="City" Width="140"></asp:TextBox> <br />
<label>Province</label><asp:TextBox ID="tProvince" runat="server" f="Province" Width="75"></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px" class="iForm">
<label>Description</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" f="Description" ></asp:TextBox> <br />
<asp:CheckBox ID="chkActive" f="Active" Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" f="Balcony" Text=" Has Balcony" runat="server" TextAlign="Right" />
</div>
<div style="clear:both"></div>
<button id="cmdSave" runat="server" class="btn" onserverclick="cmdSave_ServerClick" >
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Save</span>
</button>
<button id="cmdCancel" runat="server" class="btn" style="margin-left:15px">
<span aria-hidden="true" class="glyphicon glyphicon-arrow-left"> Back/Cancel</span>
</button>
<button id="cmdDelete" runat="server" class="btn" style="margin-left:15px">
<span aria-hidden="true" class="glyphicon glyphicon-trash"> Delete</span>
</button>
</div>
And now our ONE bit of JavaScript - but this is ALL we have to write:
Drop this right after the above div:
<script>
function PopEdit() {
var myDialog = $("#EditRecord");
myDialog.dialog({
title: "Edit Hotel Information",
modal: true,
width: 860,
appendTo: "form"
});
}
</script>
Ok, that is quite much it.
Now, we have that row button click. As noted, this is just a plane jane asp.net button, or whatever you like.
That button in the GV was this:
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn" OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
And the code for this button:
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Dim pkID = GHotels.DataKeys(gRow.RowIndex).Item("ID")
Dim cmdSQL As New SqlCommand("SELECT * from tblHotelsA where ID = #ID")
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = pkID
Dim rstData As DataTable = MyrstP(cmdSQL)
Call fLoader(Me.EditRecord, rstData.Rows(0))
ViewState("rstData") = rstData
ClientScript.RegisterStartupScript(Page.GetType(), "PopEditKey", "PopEdit()", True)
End Sub
Not a lot of code. We simple load up our "div", and then pop it with that one lone jquery.UI bit of code.
And the result is Now this:
Ok, so now we need the save button code. That is this:
Protected Sub cmdSave_ServerClick(sender As Object, e As EventArgs)
Dim rstData As DataTable = ViewState("rstData")
Call fWriterW(EditRecord, rstData.Rows(0))
Call SaveTable(rstData, "tblHotelsA")
LoadGrid()
End Sub
And the cancel/back button? Well as we know ANY post-back will collopse the dialog, so it actually does not need much code. And if you wish, I can post the code for the delete button (and we probably should provide a nice looking "confirm" delete prompt - and we can use a jQuery.Ui dialog for that - but again, use 90% server side clean vb code for the delete button.
Ok, so now the helper routines I used for above.
I have 3
MyRstP - this just accepts a sql command - retruns a table.
Public Function MyrstP(sqlCmd As SqlCommand) As DataTable
Dim rstData As New DataTable
Using sqlCmd
Using conn = New SqlConnection(My.Settings.TEST4)
conn.Open()
sqlCmd.Connection = conn
rstData.Load(sqlCmd.ExecuteReader)
End Using
End Using
Return rstData
End Function
above just saves the hassle of "over and over" having to write query code.
Then we have a routine called "fLoader". Once again, it became OH so tiring to write code over and over that just takes a data row, and shoves it out to controls on the form. So, for each control in a "div", I just make up my own "tag". I use f="data base column name goes here"
So, inside of a given div, then you see this for hotel name:
<label>HotelName</label><asp:TextBox ID="txtHotel" runat="server" f="HotelName" width="280"></asp:TextBox> <br />
<label>First Name</label><asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140"></asp:TextBox> <br />
So, for each control, I kind of cooked up my own binding - saves you have to write that code over and over.
So, floader looks like this (I just added a module1 to mycode). and thus all forms and routines can use this code. All it does is take the rstData (row(0), and move the database columns to the controls that have a tag f="column name". It is a bit of code, but after having written it, it sure makes shoving data out to controls rather easy.
Public Sub fLoader(F As HtmlGenericControl, rst As DataRow)
For Each c As System.Web.UI.Control In F.Controls
Select Case c.GetType
Case GetType(TextBox)
Dim ctlC As TextBox = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
End If
End If
Case GetType(Label)
Dim ctlC As Label = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
End If
End If
Case GetType(DropDownList)
Dim ctlC As DropDownList = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
End If
End If
Case GetType(CheckBox)
Dim ctlC As CheckBox = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
ctlC.Checked = rst(ctlC.Attributes("f"))
End If
End If
Case GetType(RadioButtonList)
Dim ctlC As RadioButtonList = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
ctlC.SelectedValue = rst(ctlC.Attributes("f"))
End If
End If
End Select
Next
End Sub
And then I have the reverse. Take from controls -> back into the rstData (data row, but from the datatable).
It really is the above code in "reverse" and takes values from controls and shoves then back into the rstData.
Public Sub fWriterW(f As HtmlGenericControl, rst As DataRow)
For Each c As System.Web.UI.Control In f.Controls
Select Case c.GetType
Case GetType(TextBox)
Dim ctlC As TextBox = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
End If
End If
Case GetType(Label)
Dim ctlC As Label = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
End If
End If
Case GetType(DropDownList)
Dim ctlC As DropDownList = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
End If
End If
Case GetType(CheckBox)
Dim ctlC As CheckBox = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
rst(ctlC.Attributes("f")) = ctlC.Checked
End If
End If
Case GetType(RadioButtonList)
Dim ctlC As RadioButtonList = c
If Not ctlC.Attributes("f") Is Nothing Then
If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
rst(ctlC.Attributes("f")) = ctlC.SelectedValue
End If
End If
End Select
Next
End Sub
and then one more routine - this routine just saves the database table BACK to the database. Hence you pass it the rstData, and table name.
Sub SaveTable(rstData As DataTable, strTable As String)
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("select * FROM " & strTable, conn)
Dim da As New SqlDataAdapter(cmdSQL)
Dim daU As New SqlCommandBuilder(da)
conn.Open()
da.Update(rstData)
End Using
End Using
End Sub
So, those little helper routines - I just place in a plane jane Module, and thus all my code can use it. It really nice since you really don't' mess with much sql, and NEVER have to mess with a boatload of parameters.
To be fair, I could have posted the ONE grid row button code. Note how it is a simple regular button - and does NOT use the GV events - but is a plane jane "click" event for server side code. And do look at the code close - note how it picks up the row clicked on, and also how it picked up the PK ID.

EXT.NET: how to render only a subset of a store into a grid?

So here's the deal: I have two grids bound to the following stores:
<ext:Store ID="storeProjects" runat="server" UseIdConfirmation="true">
<Reader>
<ext:JsonReader IDProperty="idProject" >
<Fields>
<ext:RecordField Name="idProject" Type="Int" />
<ext:RecordField Name="nmProject" Type="String" />
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
<ext:Store ID="storeProjectHistory" runat="server" UseIdConfirmation="true" >
<Reader>
<ext:JsonReader IDProperty="cdProject">
<Fields>
<ext:RecordField Name="cdProject" Type="Int" />
<ext:RecordField Name="nmProject" Type="String" />
<ext:RecordField Name="csStatus" Type="String" />
<ext:RecordField Name="dsDescription" Type="String" />
<ext:RecordField Name="dtChange" Type="Auto" DateFormat="MM/yyyy" />
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
They are "linked" (at least in theory) by having idProject in the first store equals cdProject in the second store.
On to the grids. Whenever I click a row in the first grid (bound to storeProjects), I'd like to only partially fill the second grid with the history of the selected project - in other words, a subset of storeProjectHistory where cdProject = selected idProject from the first grid - and not with the whole storeProjectHistory data.
The whole click one grid to fill another works fine with Javascript, but like I said before, it uses the whole store and I only want data of a project in particular.
I had previously made a huge mess with a ton of Javascript and it worked somehow, but I rewrote the whole code in order to make it cleaner and now I'm stuck at this particular point. I figure that I can use some grid properties and much less javascript I previously used to achieve what I want, but I can't quite figure out how. Help, please?
BTW: That's a simplified example, so don't mind fields that apparently don't make sense.
inside the grid u should use selection model first.(this is the firts grid that triger the fill event of the the second grid)
something like this
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel2" runat="server" Mode="Single">
<DirectEvents>
<Select OnEvent="RowSelect_Triger" Buffer="250">
<ExtraParams>
<%how many parameter u need decribe here-%>
<ext:Parameter Name="Id" Value="record.data.Id" Mode="Raw" />
</ExtraParams>
</Select>
</DirectEvents>
</ext:RowSelectionModel>
</SelectionModel>
later from the codebehind get the parameter (in this case id),and load the second grid depents on the this id.
int Id = int.Parse(e.ExtraParams["Id"]);

Change image inside web user control (setting up onmouseover programmatically)

Okay, so I'm fairly new to web development (but not programming), and am trying to figure out the best way to implement a mouse over image swap inside a user control.
I've tried several solutions to similar problems on SO already, but my problem appears to be unique to User Controls. I have a (user control) NavigationNenu with 4 (user control) NavigationItems on them, and essentially the NavigationItem is this:
<div class="div_navImage">
<asp:Image ID="navImage" runat="server" ImageUrl="<%this.DefaultImageUrl %>" CssClass="image_navImage" />
<div id="divIconText" runat="server"/>
</div>
with this code behind:
Private ReadOnly Property NavImageElementId As String
Get
Return navImage.GetUniqueIDRelativeTo(Me.Parent.Parent).ToString().Replace("$"c, "_"c)
End Get
End Property
<PersistenceMode(PersistenceMode.InnerProperty)>
Public Property DefaultImageUrl As String
<PersistenceMode(PersistenceMode.InnerProperty)>
Public Property HoverImageUrl As String
<PersistenceMode(PersistenceMode.InnerProperty)>
Public Property IconText As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
navImage.Attributes.Add("onmouseover", "updateImageToHover(" + NavImageElementId + ")")
navImage.Attributes.Add("onmouseout", "updateImageToDefault(" + NavImageElementId + ")")
navImage.ImageUrl = "~\" & DefaultImageUrl
divIconText.InnerText = IconText
End Sub
and the html for the nav menu:
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="NavigationMenu.ascx.vb" Inherits="[internal stuff]" %>
<%# Register Src="~/UserControls/Common/NavigationItem.ascx" TagName="navItem" TagPrefix="ucNavItem" %>
<ucNavItem:navItem ID="home" DefaultImageUrl="Resources/home_default.png" HoverImageUrl="Resources/home_hover.png" IconText="home" runat="server" />
<ucNavItem:navItem ID="ideas" DefaultImageUrl="Resources/ideas_default.png" HoverImageUrl="Resources/ideas_hover.png" IconText="ideas" runat="server" />
<ucNavItem:navItem ID="data" DefaultImageUrl="Resources/data_default.png" HoverImageUrl="Resources/data_hover.png" IconText="data" runat="server" />
<ucNavItem:navItem ID="solutions" DefaultImageUrl="Resources/solutions_default.png" HoverImageUrl="Resources/solutions_hover.png" IconText="solutions" runat="server" />
The javascript has fluctuated a bit and I don't really have a working copy right now, but the best result I was able to achieve so far was on mouse over the icon would change to the proper image, but only of the last item in the navigation menu (ie item 1 would change to the hover over icon for item 4 when moused over), so it feels like some kind of scoping or instance issue (though I'm not entirely sure that those kind of issues exist in asp.net/JS/html land).
So, is there something different that needs done when working with JS and a repeated user control? Is there some other way I should be going about what I'm attempting to achieve? I've tried a bit of jquery also, but the samples I've worked with haven't really done anything, so I'm probably setting something up incorrectly there.
Any advice to point me in the right direction?
Thanks in advance.
EDIT:
forgot to point out - the reason I'm not doing a simple swap in the page load on:
navImage.Attributes.Add("onmouseover", "updateImageToHover(" + NavImageElementId + ")")
is because I want the image to change when the text is rolled over as well, and after I implement the JS swap, I will apply the solution to the text as well (but a solution which applies to the outer div would be most welcome as well).
EDIT 2:
JS that produces bad results:
function updateImageToHover(fullName) {
var hoverImageUrl = '<%= HoverImageUrl%>';
var navImage = document.getElementById(fullName.id);
navImage.src = hoverImageUrl;
}

How Do I Pass ASP.NET Control Name to Javascript Function?

I have Googled this to death and found lots of 'answers', but none of them will work for me, so maybe you clever people could give me a 'definitive' answer?
I have a Javascript function:
function enableSaveLink() {
document.getElementById('<%= btnSaveLink.ClientID %>').removeAttribute('disabled');
}
This works fine, but obviously it is hard-coded to enable a particular control on my page. What I'd like is to be able to call this function from any control on the page, passing the name of the control I'd like to enable as a variable. So, in an ideal world, my Javascript function would look like this:
function enableControl(ctl) {
document.getElementById(ctl).removeAttribute('disabled');
}
And I'd call it like this:
<asp:button id="btnTestButton" runat="server" Text="Click Me" onclientclick="enableControl('txtTestTextbox') />
<asp:button id="txtTestTextbox" runat="server" enabled="false />
I know the way I've passed the control name would never work, but I've tried passing it in all different ways and none work, so this is just for the purposes of illustration. Can anyone tell me how to actually make this work?
You need to use the ClientID property of the control.
This will help:
<asp:button id="btnTest" runat="server" Text="Click Me"
onclientclick="enableControl('<%= lblTest.ClientID %>') />
Use the this reference (more info here):
<asp:button id="btnTest" runat="server" Text="Click Me" onclientclick="enableControl(this);" />
Then in your script:
function enableSaveLink(elem) {
elem.removeAttribute('disabled');
}
Here you are passing a reference to the object calling the function to the function, you can then just set the attribute on the element rather than finding it in the DOM.
EDIT - Just realised what your intended usage is. If you're looking to fire an event from a disabled element when clicked, then you can't do this from the element. It would need to be handled from some other enabled element. The above method works fine if you intend to disable the element when clicked - but not enable the element when clicked.
EDIT - Just to accompany my comment, if you have a uniform structure like this (i.e. where all inputs have a corresponding label - or even button) then:
<div>
<label onclick="activateSibling(this);">Input One:</label>
<input type="text" />
</div>
You could try this:
function activateSibling(label) {
label.nextSibling.removeAttribute("disabled");
}
I've made a jsFiddle demonstrating my concept in jQuery which seems to work fine.
EDIT - OK, last idea. What about custom attributes. You could add a target attribute to your clickable element which contains the Id you're going to enable, like so:
<label target="active_me" onclick="activate(this);">Click to activate</label>
<input type="text" id="active_me" disabled="disabled" />
And your script:
function activate(label) {
var inputId = this.getAttribute("target");
var input = document.getElementById(inputId);
input.removeAttribute("disabled");
}
Although, it's starting to feel like we're fighting against the technology a little and we're not too far removed from ctrlInput.ClientID. But I suppose this makes your markup a little cleaner and gives you a function that's bindable en masse.
Ok, I've cracked it. There are probably more ways than one to do this, but this is fairly elegant.
My Javascript function:
function enableControl(ctl) {
document.getElementById(ctl).removeAttribute('disabled');
}
My ASP.NET markup:
<asp:Button ID="btnTestButton" runat="server" Text="Click to enable" OnClientClick="enableControl('txtTestTextbox');" />
<asp:TextBox ID="txtTestTextBox" runat="server" enabled="false" ClientIDMode="Static" />
The key is the ClientIDMode property, which, when set to static, means that the control's client-side ID when it is rendered will match the ID you give it in markup. If it's within a naming container you may need to include that in the variable passed in the function call. See here for more info about ClientIDMode.
Anyway, this works for me! Thanks for your input, everyone.
ClientID is used for getting server side control on javascript.
var element=document.getElementById('<%=lblTest.ClientID%>');

How to find and modify an asp.net control with JavaScript?

This has been bothering me for quite some time. I'm simply trying to change the value of a textbox defined in asp.net, which normally works when it is not within a LoggedInTemplate.
I've searched everywhere on the net and even here, but the only thing I can find close to doing what I need is here Finding an asp:button and asp:textbox in Javascript. Unfortunately that doesn't work. Here's what I have so far:
<head id="Head1" runat="server">
<script src="../../scripts/webeffects.js" type="text/javascript" language="javascript"></script>
</head>
<asp:LoginView ID="LoginView1" runat="server">
<LoggedInTemplate>
<div class="lotto_pick_container">
<table runat="server" id="tblLottoPick">
<tr><th colspan="3">Pick a Lotto Number</th></tr>
<tr>
<td><asp:TextBox ID="txt1stNum" runat="server"></asp:TextBox></td>
<td><asp:TextBox ID="txt2ndNum" runat="server"></asp:TextBox></td>
<td><asp:TextBox ID="txt3rdNum" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Button ID="cmdSubmitPick" runat="server" Text="Submit Lotto Number"
onclientclick="return validateLottoPicks()" /></td>
</tr>
</table>
</div>
</LoggedInTemplate>
</asp:LoginView>
Right now I'm trying to use an external js script to find a textbox and modify it with an arbitrary value of 12, just so that I know it can work:
function validateLottoPicks() {
document.getElementById('<%= LoginView1.FindControl("txt2ndNum").ClientID %>').value = 12
}
When I debug this with Firebug it seems all my other code works, except for this one function. I have verified the function gets called, it's just this line that doesn't work. Can someone please provide some guidance? I'll send milk and cookies.
Update:
Thanks for all the help from everyone. This was my first time using Stack Overflow and I was definitely impressed by the quick responses.
It turns out my actual problem was that using <%= LoginView1.FindControl("txt2ndNum").ClientID %> does not work in external js scripts. I didn't know this. Once, I put the function in the header of my page everything worked. Now I'm going to avoid using ASP.NET controls because I don't want to deal with that again, and it makes more sense if I ever decide to use something other than ASP.NET.
The problem is that you have set visible=false on this line
<table runat="server" id="tblLottoPick" visible="false">
From that moment the controls are not rendered the javascript can not find this control. If you do not wish to show this table use css, for example style="display:none;" so its rendered but not visible. All the rest seems to me that working.
Update
From the comments also seems that this code is not inside the aspx page, so the ClientID can not work and not found. Add this somewhere in the header in the page that have this LoginView1 control.
function validateLottoPicks() {
document.getElementById('<%= LoginView1.FindControl("txt2ndNum").ClientID %>').value = 12
}
Try
tblLottoPick.FindControl("txt2ndNum").ClientID instead.
Try putting this into a javascript string variable. What are you getting?
'<%= LoginView1.FindControl("txt2ndNum").ClientID %>'
Because you shouldn't have to do that. Can you just do this?
document.getElementById('txt2ndNum')
Also, check in firebug to see what the ID value is set to for that control (i.e. the rendered textbox). I mean see what it's rendered as. You just need to get the right id.

Categories

Resources