using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.ComponentModel;
using System.Drawing.Design;
using System.Web.UI.WebControls;
using System.Web;
using System.Security.Permissions;
using System.Reflection;
using System.Globalization;
using Mullivan.Web.UI.Design.WebControls;
namespace Mullivan.Web.UI.WebControls
{
[ToolboxData("<{0}:JQueryAccordion Width=\"200\" Height=\"150\" runat=\"server\"></{0}:JQueryAccordion>"),
Designer(typeof(JQueryAccordionDesigner)),
PersistChildren(false),
ParseChildren(true),
Bindable(false),
AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class JQueryAccordion : WebControl
{
// Fields
private int _cacheSectionIndex = -1;
private bool _initialized;
private JQueryAccordionSectionCollection _sectionCollection = null;
private static readonly object EventActiveSectionChanged = new object();
private Type _tControl = null;
private Type _tOccasionalFields = null;
private MethodInfo _miRenderChildrenInternal;
private MethodInfo _miEnsureOccasionalFields;
private FieldInfo _fiOccasionalFields;
private object _objOccasionalFields;
private FieldInfo _fiOccasionalFieldsControls;
// Event
[Category("Behavior")]
public event EventHandler ActiveSectionChanged
{
add
{
base.Events.AddHandler(EventActiveSectionChanged, value);
}
remove
{
base.Events.RemoveHandler(EventActiveSectionChanged, value);
}
}
// Methods
public JQueryAccordion()
: base(HtmlTextWriterTag.Div)
{
_tControl = typeof(Control);
_miEnsureOccasionalFields = _tControl.GetMethod("EnsureOccasionalFields", BindingFlags.Instance | BindingFlags.NonPublic);
_miRenderChildrenInternal = _tControl.GetMethod("RenderChildrenInternal", BindingFlags.NonPublic | BindingFlags.Instance);
_miEnsureOccasionalFields.Invoke(this, null);
_fiOccasionalFields = _tControl.GetField("_occasionalFields", BindingFlags.NonPublic | BindingFlags.Instance);
_objOccasionalFields = _fiOccasionalFields.GetValue(this);
_tOccasionalFields = _objOccasionalFields.GetType();
_fiOccasionalFieldsControls = _tOccasionalFields.GetField("Controls", BindingFlags.Instance | BindingFlags.Public);
this._cacheSectionIndex = -1;
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public JQueryAccordionSection ActiveSection
{
get
{
int activeTabIndex = this.ActiveSectionIndex;
if ((activeTabIndex < 0) || (activeTabIndex >= this.Sections.Count))
{
return null;
}
return this.Sections[activeTabIndex];
}
set
{
int index = this.Sections.IndexOf(value);
if (index < 0)
{
throw new ArgumentOutOfRangeException("value");
}
this.ActiveSectionIndex = index;
}
}
[DefaultValue(-1),
Category("Behavior"),
Browsable(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int ActiveSectionIndex
{
get
{
if (this._initialized)
{
if (this.Sections.Count == 0)
{
this._cacheSectionIndex = -1;
}
else if (_cacheSectionIndex >= this.Sections.Count)
{
this._cacheSectionIndex = this.Sections.Count - 1;
}
return this._cacheSectionIndex;
}
return _cacheSectionIndex;
}
set
{
if (!_initialized)
{
this._cacheSectionIndex = value;
}
else
{
if (value < -1)
{
throw new ArgumentOutOfRangeException("value");
}
if (value >= this.Sections.Count)
{
throw new ArgumentOutOfRangeException("value");
}
if (this._cacheSectionIndex != value)
{
this._cacheSectionIndex = value;
OnActiveTabChanged(new EventArgs());
}
}
}
}
[Category("Behavior"),
Browsable(true)]
public bool Collapsible
{
get
{
return (this.ViewState["Collapsible"] != null ? (bool)this.ViewState["Collapsible"] : false);
}
set
{
this.ViewState["Collapsible"] = value;
}
}
[Category("Behavior"), DisplayName("Selection Mode"),
Browsable(true)]
public JQueryAccordionSelectionMode SelectionMode
{
get
{
return (this.ViewState["SelectionMode"] != null ? (JQueryAccordionSelectionMode)this.ViewState["SelectionMode"] : JQueryAccordionSelectionMode.Click);
}
set
{
this.ViewState["SelectionMode"] = value;
}
}
[DefaultValue(typeof(Unit), ""), Category("Appearance")]
public override Unit Height
{
get
{
return base.Height;
}
set
{
if (!value.IsEmpty && (value.Type != UnitType.Pixel))
{
throw new ArgumentOutOfRangeException("value", "Height must be set in pixels only, or Empty.");
}
base.Height = value;
}
}
[DefaultValue(typeof(Unit), ""), Category("Appearance")]
public override Unit Width
{
get
{
return base.Width;
}
set
{
base.Width = value;
}
}
[Category("Behavior"), DefaultValue("")]
public string OnClientActiveSectionChanged
{
get
{
return (this.ViewState["OnClientActiveSectionChanged"] != null ? this.ViewState["OnClientActiveSectionChanged"].ToString() : string.Empty);
}
set
{
this.ViewState["OnClientActiveSectionChanged"] = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Browsable(true),
Themeable(false),
Editor(typeof(JQueryAccordionSectionCollectionEditor), typeof(UITypeEditor)),
PersistenceMode(PersistenceMode.InnerProperty)]
public JQueryAccordionSectionCollection Sections
{
get
{
if (this._sectionCollection == null)
{
this._sectionCollection = new JQueryAccordionSectionCollection(this);
}
return this._sectionCollection;
}
}
internal JQueryAccordionSectionControlCollection SectionControls
{
get
{
JQueryAccordionSectionControlCollection collection = (JQueryAccordionSectionControlCollection)
_fiOccasionalFieldsControls.GetValue(_objOccasionalFields);
if (collection == null)
{
collection = (JQueryAccordionSectionControlCollection)this.CreateControlCollection();
_fiOccasionalFieldsControls.SetValue(_objOccasionalFields, collection);
}
return collection;
}
}
public string UniqueID
{
get
{
return base.UniqueID;
}
set
{
}
}
[Browsable(false)]
public string ClientJQueryControlId
{
get
{
this.EnsureID();
return "jq" + this.ClientID;
}
}
[Browsable(false)]
public string ClientActiveSectionControlId
{
get
{
this.EnsureID();
return "jq" + this.ClientID + "_ActiveSection";
}
}
protected override void AddedControl(Control control, int index)
{
((JQueryAccordionSection)control).SetOwner(this);
base.AddedControl(control, index);
}
protected override void AddParsedSubObject(object obj)
{
JQueryTab child = obj as JQueryTab;
if (child != null)
{
this.Controls.Add(child);
}
else if (!(obj is LiteralControl))
{
throw new HttpException(string.Format(CultureInfo.CurrentCulture, "TabContainer cannot have children of type '{0}'.", new object[] { obj.GetType() }));
}
}
protected virtual void OnActiveTabChanged(EventArgs e)
{
EventHandler handler = base.Events[EventActiveSectionChanged] as EventHandler;
if (handler != null)
{
handler(this, e);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ClientScriptProxy p = ClientScriptProxy.Current;
this.Page.RegisterRequiresControlState(this);
JQueryUtil.RegisterRequiredResources(p, this);
#if DEBUG
p.RegisterClientScriptInclude(this, WebResources.JQUERY_JAVASCRIPT_UI_ACCORDION, false);
#endif
p.RegisterClientScriptInclude(this, WebResources.JQUERY_JAVASCRIPT_UI_EXT_ACCORDION, false);
if (!this.Page.IsPostBack)
{
if (this.Sections.Count > 0)
{
if (_cacheSectionIndex > -1 && _cacheSectionIndex < this.Sections.Count)
{
this.ActiveSectionIndex = _cacheSectionIndex;
}
else
this.ActiveSectionIndex = 0;
}
}
else
{
this.ActiveSectionIndex = int.Parse(this.Page.Request.Form[ClientActiveSectionControlId]);
}
this._initialized = true;
}
protected override void RemovedControl(Control control)
{
JQueryAccordionSection panel = control as JQueryAccordionSection;
this.Sections.Remove(panel);
}
protected override void OnPreRender(EventArgs e)
{
ClientScriptProxy p = ClientScriptProxy.Current;
string strSelectedSectionChanged = ClientJQueryControlId + "_SelectedSectionChanged";
p.RegisterHiddenField(this, ClientActiveSectionControlId, this.ActiveSectionIndex.ToString());
StringBuilder sbStartup = new StringBuilder();
sbStartup.Append("var ");
sbStartup.Append(ClientJQueryControlId);
sbStartup.Append(" = jQuery('#");
sbStartup.Append(this.ClientID);
sbStartup.AppendLine("');");
//Invoke client side rendering
sbStartup.Append("var ");
sbStartup.Append(ClientActiveSectionControlId);
sbStartup.Append(" = document.getElementById('");
sbStartup.Append(ClientActiveSectionControlId);
sbStartup.AppendLine("');");
sbStartup.Append("$(window).bind('load', ");
sbStartup.Append("Init_");
sbStartup.Append(ClientJQueryControlId);
sbStartup.AppendLine(");");
sbStartup.Append("function Init_");
sbStartup.Append(ClientJQueryControlId);
sbStartup.AppendLine("(){");
sbStartup.Append(ClientJQueryControlId);
sbStartup.AppendLine(".accordion();");
//Set Selection Mode
sbStartup.Append(ClientJQueryControlId);
sbStartup.Append(".accordion('option', 'event', '");
sbStartup.Append(this.SelectionMode.ToString().ToLower());
sbStartup.AppendLine("');");
//Set collapsible
sbStartup.Append(ClientJQueryControlId);
sbStartup.Append(".accordion('option', 'collapsible', ");
sbStartup.Append(this.Collapsible.ToString().ToLower());
sbStartup.AppendLine(");");
//Set selected tab
sbStartup.Append("if(parseInt(");
sbStartup.Append(ClientActiveSectionControlId);
sbStartup.Append(".value) > 0)");
sbStartup.AppendLine("{");
sbStartup.Append(ClientJQueryControlId);
sbStartup.Append(".accordion('activate', parseInt(");
sbStartup.Append(ClientActiveSectionControlId);
sbStartup.AppendLine(".value));");
sbStartup.AppendLine("}");
//set handler for SelectedTabChanged
sbStartup.Append(ClientJQueryControlId);
sbStartup.Append(".bind('accordionchange', function (event, ui){");
sbStartup.Append(strSelectedSectionChanged);
sbStartup.AppendLine("(event, ui);});");
sbStartup.AppendLine("}");
#region "Tab Selection"
sbStartup.Append("function ");
sbStartup.Append(strSelectedSectionChanged);
sbStartup.AppendLine("(event, ui){");
sbStartup.Append(ClientJQueryControlId);
sbStartup.AppendLine(".accordion('getIndexOfHeader', ui.newHeader, function(result){ ");
sbStartup.Append(ClientActiveSectionControlId);
sbStartup.AppendLine(".value = result;");
if (!string.IsNullOrEmpty(this.OnClientActiveSectionChanged))
{
sbStartup.Append("try{");
sbStartup.Append(this.OnClientActiveSectionChanged);
sbStartup.AppendLine("(event,ui);}catch(e){alert(e.message);}");
}
Dictionary<string, string> sectionEvents = new Dictionary<string, string>();
foreach (JQueryAccordionSection sec in this.Sections)
{
if (!string.IsNullOrEmpty(sec.OnClientSectionSelected))
sectionEvents.Add(sec.Position.ToString(), sec.OnClientSectionSelected);
}
if (sectionEvents.Count > 0)
{
sbStartup.AppendLine("switch(result){");
foreach (string key in sectionEvents.Keys)
{
sbStartup.Append("case ");
sbStartup.Append(key);
sbStartup.AppendLine(":");
sbStartup.Append("try{");
sbStartup.Append(sectionEvents[key]);
sbStartup.Append("(event,ui);");
sbStartup.AppendLine("}catch(e){alert(e.message);}");
sbStartup.AppendLine("break;");
}
sbStartup.AppendLine("default:");
sbStartup.AppendLine("break;");
sbStartup.AppendLine("}");
}
sbStartup.AppendLine("});");
sbStartup.AppendLine("}");
#endregion "Tab Selection"
p.RegisterStartupScript(this.Page, typeof(WebResources), "_jsStartup__" + this.ClientID, sbStartup.ToString(), true);
base.OnPreRender(e);
}
public override ControlCollection Controls
{
get
{
//Fakes out the Collection Editor for the Tabs
return new ControlCollection(this);
}
}
protected override ControlCollection CreateControlCollection()
{
return new JQueryAccordionSectionControlCollection(this);
}
protected override object SaveControlState()
{
Pair pair = new Pair();
pair.First = base.SaveControlState();
pair.Second = this.ActiveSectionIndex;
if ((pair.First == null) && (pair.Second == null))
{
return null;
}
return pair;
}
public enum JQueryAccordionSelectionMode
{
Click,
DblClick,
MouseOver,
MouseDown,
MouseUp
}
}
}