DropDown kalender kontroll
Förord
När man har ett datumfält och vill plocka ut datumet genom att välja en dag i en kalender så bygger man oftast en lösning där man öppnar ett pop-up fönster för kalendern. Paul Kimmel har publicerat en artikel där man istället öppnar kalendern som en drop-down i anslutning till datumfältet. Detta har jag nu utvecklat till en kontroll som tillåter flera datumfält på samma sida.Innehåll
»»
»
»
»
»
Introduktion
Paul Kimmel publicerade en artikel om hur man bygger en drop-down kalender för sina datumfält istället för att öppna ett pop-up fönster. Nackdelen med Pauls artikel är, som han själv påpekar, att det inte går att ha flera datumfält på samma sida. För att klara det kan man bygga en kontroll, och det har jag gjort.Kontrollen ser till att rätt kalender öppnas när man klickar på en datumknapp och att datumet hamnar i rätt datumfält.
Kontrollen
Först bygger vi vår kontroll. Den består av en textbox, en kalender och en knapp. Ett javascript används för att tända och släcka kalendern.CalendarDropDownControl.ascx
<%@ Control Language="vb" AutoEventWireup="false" Codebehind="CalendarDropDownControl.ascx.vb"
Inherits="pdc.CalendarDropDownControl" %>
BackColor="White" Width="200px"
ForeColor="Black" Height="180px" Font-Size="8pt"
Font-Names="Verdana" BorderColor="#999999"
BorderStyle="Outset" DayNameFormat="FirstLetter" CellPadding="4">
För att lättare kunna anpass sin kalender kan man lägga all visuell formattering i code-behind, lägga till properties och på så sätt kunna ställa in utseendet utifrån sidan man inkluderar kontrollen i. Men det är en helt annan artikel. :)
Nu lägger vi till vår code-behind.
CalendarDropDownControl.ascx.vb
Public ReadOnly Property GetDate() As String
Get
Return Me.TextBox1.Text
End Get
End Property
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim OnClick As String
OnClick = "function OnClick(id)" & vbCrLf & _
"{" & vbCrLf & _
" if( isVisible(id) ) {" & vbCrLf & _
" hidelayer(id);" & vbCrLf & _
" } else {" & vbCrLf & _
" showlayer(id);" & vbCrLf & _
" }" & vbCrLf & _
"}" & vbCrLf
Page.RegisterClientScriptBlock("SwitchCalendar", _
"<script language='JavaScript'>" & vbCrLf & _
OnClick & vbCrLf & _
"</script>" & vbCrLf)
btnGetDate.Attributes.Add("OnClick", "OnClick('div" & Me.ID & "');return false;")
End Sub
Private Sub Calendar1_SelectionChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Calendar1.SelectionChanged
TextBox1.Text = Calendar1.SelectedDate.ToShortDateString()
Dim div As System.Web.UI.Control = Page.FindControl("divCalendar")
If TypeOf div Is HtmlGenericControl Then
CType(div, HtmlGenericControl).Style.Add("display", "none")
End If
End Sub
End Class
I Page_Load skapar vi vårt JavaScript som en sträng och sedan skapar vi det på sidan med RegisterClientScriptBlock. Anledningen till detta är att om vi har flera datumfält på en sida så vill vi ändå bara ha en funktion som heter OnClick. Om man inte gör på detta sätt och lägger till 2 st kontroller så kommer ni att se två identiska funktioner i source-koden.
Vi lägger även till ett OnClick-attribut på kalenderknappen. Det innebär att funktionen OnClick kommer att köras när man klickar på knappen. "Return False" som också läggs på knappen gör att knappen inte gör någon PostBack. Utan detta så visas kalendern och sedan görs en PostBack och kalendern försvinner.
Det finns även en egenskap som heter GetDate. Den är readonly och returnerar det som står i datumfältet. Här returnerar vi den som en sträng men det kan vara bra att istället lägga på en validator som kontrollerar att fältet innehåller ett datum och sedan returnerar det som ett datum.
Det sista som behövs i code-behind är Calendar1_SelectionChanged. En Sub som stoppar in det valda datumet i textboxen.
JavaScript
Som ni kanske märkt så används funktionerna isVisible, hidelayer och showlayer i OnClick-funktionen. Dessa funktioner finns i en .js fil med standardfunktioner. Nackdelen är att denna fil måste inkluderas i varje fil där kontrollen finns. Fördelen är att man enkelt kan återanvända sina JavaScript funktioner. Dessa funktioner är cross-browser och för att uppdatera till nya webbläsare så behöver man bara ändra i sin .js fil.functions.js
function browsercheck(){
this.ver=navigator.appVersion
this.agent=navigator.userAgent
this.dom=document.getElementById?1:0
this.opera5=(navigator.userAgent.indexOf("Opera")>-1 && document.getElementById)?1:0
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
this.ie=this.ie4||this.ie5||this.ie6
this.mac=this.agent.indexOf("Mac")>-1
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
this.ns4=(document.layers && !this.dom)?1:0;
this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
return this
}
var bw=new browsercheck()
function showlayer(id) {
if (bw.ns4) {
document.layers[id].visibility = "show"
} else if (bw.ie) {
document.all[id].style.visibility = "visible"
} else {
document.getElementById(id).style.visibility = "visible"
}
}
function hidelayer(id) {
if (bw.ns4) {
document.layers[id].visibility = "hide"
} else if (bw.ie) {
document.all[id].style.visibility = "hidden"
} else {
document.getElementById(id).style.visibility = "hidden"
}
}
function isVisible(id) {
if (bw.ns4) {
if (document.layers[id].visibility == "show") return true
else return false
} else if (bw.ie) {
if (document.all[id].style.visibility == "visible") return true
else return false
} else {
if (document.getElementById(id).style.visibility == "visible") return true
else return false
}
}
Ett test
Nu ska vi testa det hela. Vi skapar en .aspx sida som använder två datumfält. Vi lägger även till en knapp som hämtar de valda datumen och visar i en Label.CalendarTest.aspx
<%@ Register TagPrefix="PDC" TagName="CalendarDropDownControl"
Src="controls\CalendarDropDownControl.ascx" %>
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="CalendarTest.aspx.vb" Inherits="pdc.CalendarTest" %>
CalendarTest
<script language="javascript" src="include/functions.js"></script>
Det enda som behövs nu är en funktion som hanterar submit-knappen och visar de valda datumen.
CalendarTest.aspx.vb
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
lblResult.Text = "1: " & myCal1.GetDate & "
2: " & myCal2.GetDate
End Sub
Avslutning
Nu har vi byggt en kontroll som vi kan stoppa in på de sidor där vi behöver ett datumfält.Det finns viss funktionalitet man kan bygga till om man så önskar, t.ex.:
- Göra om den till en server kontroll
- Validering på datumfältet så att det verkligen är ett korrekt datum
- Möjlighet att stänga kalendern genom att klicka någonstans i fönstret utanför kalendern
- Egenskaper för att kunna ändra design och layout från den sida där man inkluderar kontrollen
Resurser
Ett färdigt testprojekt kan laddas ner från filarkivet och om ni vill prova hur det fungerar så finns det även en demonstration på Ett färdigt testprojekt med all kod kan laddas ner från
Paul Kimmels artikel
Happy coding!
Patrik Dahlén
0 Kommentarer