diff --git a/.gitignore b/.gitignore
index 9ddd1fd..ebb0003 100644
--- a/.gitignore
+++ b/.gitignore
@@ -330,4 +330,4 @@ ASALocalRun/
.mfractor/
# Error and log files
-**/App_Data/*
\ No newline at end of file
+#**/App_Data/*
\ No newline at end of file
diff --git a/BuildProcessTemplates/DefaultTemplate.11.1.xaml b/BuildProcessTemplates/DefaultTemplate.11.1.xaml
deleted file mode 100644
index bf54edf..0000000
--- a/BuildProcessTemplates/DefaultTemplate.11.1.xaml
+++ /dev/null
@@ -1,543 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings()]
- [False]
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.TestSpecList(New Microsoft.TeamFoundation.Build.Workflow.Activities.AgileTestPlatformSpec("**\*test*.dll"))]
- ["$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)"]
- [False]
- [True]
- [True]
- [Microsoft.TeamFoundation.Build.Workflow.Activities.CleanWorkspaceOption.All]
-
-
-
- [Microsoft.TeamFoundation.Build.Workflow.Activities.CodeAnalysisOption.AsConfigured]
- [True]
- [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto]
- [True]
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.SourceAndSymbolServerSettings(True, Nothing)]
- [True]
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }]
- [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]
-
-
-
-
-
-
- All
- 11.0
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BuildProcessTemplates/LabDefaultTemplate.11.xaml b/BuildProcessTemplates/LabDefaultTemplate.11.xaml
deleted file mode 100644
index 9e1fb0b..0000000
--- a/BuildProcessTemplates/LabDefaultTemplate.11.xaml
+++ /dev/null
@@ -1,208 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 11.0
-
-
-
-
-
- 920,3702
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
-
-
-
-
-
-
- [LabWorkflowParameters.BuildDetails.BuildUri]
-
-
- [ChildBuildDetail.Uri]
-
-
-
-
-
-
-
-
-
-
-
- [BuildLocation]
-
-
- [If(LabWorkflowParameters.BuildDetails.Configuration Is Nothing, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsEmpty Or (SelectedBuildDetail.Information.GetNodesByType(Microsoft.TeamFoundation.Build.Common.InformationTypes.ConfigurationSummary, True)).Count = 1, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsPlatformEmptyOrAnyCpu, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Platform + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration)))]
-
-
-
-
-
-
-
-
-
-
-
- [LabEnvironmentUri]
-
-
- [LabWorkflowParameters.EnvironmentDetails.LabEnvironmentUri.ToString()]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [PostDeploymentSnapshotName]
-
-
- [If(LabWorkflowParameters.BuildDetails.IsTeamSystemBuild = True,String.Format("{0}_{1}_{2}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildNumber,BuildDetail.BuildNumber),String.Format("{0}_{1}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildDetail.BuildNumber))]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [BuildStatus]
-
-
- [Microsoft.TeamFoundation.Build.Client.BuildStatus.PartiallySucceeded]
-
-
-
-
-
-
- [BuildStatus]
-
-
- [Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed]
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/BuildProcessTemplates/UpgradeTemplate.xaml b/BuildProcessTemplates/UpgradeTemplate.xaml
deleted file mode 100644
index b3ee07f..0000000
--- a/BuildProcessTemplates/UpgradeTemplate.xaml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }]
-
-
-
- [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto]
- [False]
- [False]
-
-
-
-
-
-
-
-
-
- [Microsoft.TeamFoundation.VersionControl.Client.RecursionType.OneLevel]
- [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]
-
-
-
- All
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/EFMVC.Azure/EFMVC.Azure.ccproj b/EFMVC.Azure/EFMVC.Azure.ccproj
new file mode 100644
index 0000000..2f15cf1
--- /dev/null
+++ b/EFMVC.Azure/EFMVC.Azure.ccproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ 3ece0219-c411-432f-8013-0b7b69f9f8fc
+ Library
+ Properties
+ EFMVC.Azure
+ EFMVC.Azure
+ True
+ EFMVC.Azure
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+ EFMVC.Web
+ {169afe38-1ca2-4624-bdc4-78c6653b04bd}
+ True
+ Web
+ EFMVC.Web
+ True
+
+
+
+
+
+
+
+ Content
+
+
+
+
+ 10.0
+ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\2.0\
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Azure/EFMVC.WebContent/diagnostics.wadcfg b/EFMVC.Azure/EFMVC.WebContent/diagnostics.wadcfg
new file mode 100644
index 0000000..061cd69
--- /dev/null
+++ b/EFMVC.Azure/EFMVC.WebContent/diagnostics.wadcfg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Azure/ServiceConfiguration.Cloud.cscfg b/EFMVC.Azure/ServiceConfiguration.Cloud.cscfg
new file mode 100644
index 0000000..c438bc8
--- /dev/null
+++ b/EFMVC.Azure/ServiceConfiguration.Cloud.cscfg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Azure/ServiceConfiguration.Local.cscfg b/EFMVC.Azure/ServiceConfiguration.Local.cscfg
new file mode 100644
index 0000000..c438bc8
--- /dev/null
+++ b/EFMVC.Azure/ServiceConfiguration.Local.cscfg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Azure/ServiceDefinition.csdef b/EFMVC.Azure/ServiceDefinition.csdef
new file mode 100644
index 0000000..2d87748
--- /dev/null
+++ b/EFMVC.Azure/ServiceDefinition.csdef
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.CommandProcessor/Command/CommandHandlerNotFoundException.cs b/EFMVC.CommandProcessor/Command/CommandHandlerNotFoundException.cs
new file mode 100644
index 0000000..ad5625b
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/CommandHandlerNotFoundException.cs
@@ -0,0 +1,11 @@
+using System;
+namespace EFMVC.CommandProcessor.Command
+{
+ public class CommandHandlerNotFoundException : Exception
+ {
+ public CommandHandlerNotFoundException(Type type) : base(string.Format("Command handler not found for command type: {0}", type))
+ {
+ }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/CommandResult.cs b/EFMVC.CommandProcessor/Command/CommandResult.cs
new file mode 100644
index 0000000..0719085
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/CommandResult.cs
@@ -0,0 +1,13 @@
+namespace EFMVC.CommandProcessor.Command
+{
+ public class CommandResult : ICommandResult
+ {
+ public CommandResult(bool success)
+ {
+ this.Success = success;
+ }
+
+ public bool Success { get; protected set; }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/CommandResults.cs b/EFMVC.CommandProcessor/Command/CommandResults.cs
new file mode 100644
index 0000000..d0f5d7f
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/CommandResults.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Linq;
+namespace EFMVC.CommandProcessor.Command
+{
+ public class CommandResults : ICommandResults
+ {
+ private readonly List results = new List();
+
+ public void AddResult(ICommandResult result)
+ {
+ this.results.Add(result);
+ }
+
+ public ICommandResult[] Results
+ {
+ get
+ {
+ return this.results.ToArray();
+ }
+ }
+
+ public bool Success
+ {
+ get
+ {
+ return this.results.All(result => result.Success);
+ }
+ }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/ICommand.cs b/EFMVC.CommandProcessor/Command/ICommand.cs
new file mode 100644
index 0000000..b25ed66
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/ICommand.cs
@@ -0,0 +1,5 @@
+namespace EFMVC.CommandProcessor.Command
+{
+ public interface ICommand { }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/ICommandHandler.cs b/EFMVC.CommandProcessor/Command/ICommandHandler.cs
new file mode 100644
index 0000000..73af844
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/ICommandHandler.cs
@@ -0,0 +1,8 @@
+namespace EFMVC.CommandProcessor.Command
+{
+ public interface ICommandHandler where TCommand: ICommand
+ {
+ ICommandResult Execute(TCommand command);
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/ICommandResult.cs b/EFMVC.CommandProcessor/Command/ICommandResult.cs
new file mode 100644
index 0000000..f755406
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/ICommandResult.cs
@@ -0,0 +1,8 @@
+namespace EFMVC.CommandProcessor.Command
+{
+ public interface ICommandResult
+ {
+ bool Success { get; }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/ICommandResults.cs b/EFMVC.CommandProcessor/Command/ICommandResults.cs
new file mode 100644
index 0000000..290d291
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/ICommandResults.cs
@@ -0,0 +1,10 @@
+namespace EFMVC.CommandProcessor.Command
+{
+ public interface ICommandResults
+ {
+ ICommandResult[] Results { get; }
+
+ bool Success { get; }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Command/IValidationHandler.cs b/EFMVC.CommandProcessor/Command/IValidationHandler.cs
new file mode 100644
index 0000000..fd0c233
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/IValidationHandler.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor;
+using EFMVC.Core.Common;
+
+namespace EFMVC.CommandProcessor.Command
+{
+ public interface IValidationHandler where TCommand : ICommand
+ {
+ IEnumerable Validate(TCommand command);
+ }
+}
diff --git a/EFMVC.CommandProcessor/Command/ValidationHandlerNotFoundException.cs b/EFMVC.CommandProcessor/Command/ValidationHandlerNotFoundException.cs
new file mode 100644
index 0000000..13df3f4
--- /dev/null
+++ b/EFMVC.CommandProcessor/Command/ValidationHandlerNotFoundException.cs
@@ -0,0 +1,11 @@
+using System;
+namespace EFMVC.CommandProcessor.Command
+{
+ public class ValidationHandlerNotFoundException : Exception
+ {
+ public ValidationHandlerNotFoundException(Type type)
+ : base(string.Format("Validation handler not found for command type: {0}", type))
+ {
+ }
+ }
+}
diff --git a/EFMVC.CommandProcessor/Dispatcher/DefaultCommandBus.cs b/EFMVC.CommandProcessor/Dispatcher/DefaultCommandBus.cs
new file mode 100644
index 0000000..e3ec3fd
--- /dev/null
+++ b/EFMVC.CommandProcessor/Dispatcher/DefaultCommandBus.cs
@@ -0,0 +1,31 @@
+
+using System.Collections.Generic;
+using System.Web.Mvc;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Core.Common;
+namespace EFMVC.CommandProcessor.Dispatcher
+{
+ public class DefaultCommandBus : ICommandBus
+ {
+ public ICommandResult Submit(TCommand command) where TCommand: ICommand
+ {
+ var handler = DependencyResolver.Current.GetService>();
+ if (!((handler != null) && handler is ICommandHandler))
+ {
+ throw new CommandHandlerNotFoundException(typeof(TCommand));
+ }
+ return handler.Execute(command);
+
+ }
+ public IEnumerable Validate(TCommand command) where TCommand : ICommand
+ {
+ var handler = DependencyResolver.Current.GetService>();
+ if (!((handler != null) && handler is IValidationHandler))
+ {
+ throw new ValidationHandlerNotFoundException(typeof(TCommand));
+ }
+ return handler.Validate(command);
+ }
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/Dispatcher/ICommandBus.cs b/EFMVC.CommandProcessor/Dispatcher/ICommandBus.cs
new file mode 100644
index 0000000..aad6873
--- /dev/null
+++ b/EFMVC.CommandProcessor/Dispatcher/ICommandBus.cs
@@ -0,0 +1,12 @@
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Core.Common;
+using System.Collections.Generic;
+namespace EFMVC.CommandProcessor.Dispatcher
+{
+ public interface ICommandBus
+ {
+ ICommandResult Submit(TCommand command) where TCommand: ICommand;
+ IEnumerable Validate(TCommand command) where TCommand : ICommand;
+ }
+}
+
diff --git a/EFMVC.CommandProcessor/EFMVC.CommandProcessor.csproj b/EFMVC.CommandProcessor/EFMVC.CommandProcessor.csproj
new file mode 100644
index 0000000..ffa9e56
--- /dev/null
+++ b/EFMVC.CommandProcessor/EFMVC.CommandProcessor.csproj
@@ -0,0 +1,75 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {955FD94A-BBC1-4469-889A-740FB98338DE}
+ Library
+ Properties
+ EFMVC.CommandProcessor
+ EFMVC.CommandProcessor
+ v4.5
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}
+ EFMVC.Core
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.CommandProcessor/Properties/AssemblyInfo.cs b/EFMVC.CommandProcessor/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ba839a3
--- /dev/null
+++ b/EFMVC.CommandProcessor/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("EFMVC.CommandProcessor")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("EFMVC.CommandProcessor")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b39b9f04-4b4b-4875-b7ed-2e5340060e34")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/EFMVC.Core/Common/Md5Encrypt.cs b/EFMVC.Core/Common/Md5Encrypt.cs
new file mode 100644
index 0000000..f20e430
--- /dev/null
+++ b/EFMVC.Core/Common/Md5Encrypt.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Security.Cryptography;
+
+namespace EFMVC.Core.Common
+{
+ public static class Md5Encrypt
+ {
+ public static string Md5EncryptPassword(string data)
+ {
+ var encoding = new ASCIIEncoding();
+ var bytes = encoding.GetBytes(data);
+ var hashed = MD5.Create().ComputeHash(bytes);
+ return Encoding.UTF8.GetString(hashed);
+ }
+ }
+}
diff --git a/EFMVC.Core/Common/ValidationResult.cs b/EFMVC.Core/Common/ValidationResult.cs
new file mode 100644
index 0000000..36cf816
--- /dev/null
+++ b/EFMVC.Core/Common/ValidationResult.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace EFMVC.Core.Common
+{
+ ///
+ /// Describes the result of a validation of a potential change through a business service.
+ ///
+ public class ValidationResult
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ValidationResult()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the memeber.
+ /// The message.
+ public ValidationResult(string memeberName, string message)
+ {
+ this.MemberName = memeberName;
+ this.Message = message;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ public ValidationResult(string message)
+ {
+ this.Message = message;
+ }
+
+ ///
+ /// Gets or sets the name of the member.
+ ///
+ ///
+ /// The name of the member. May be null for general validation issues.
+ ///
+ public string MemberName { get; set; }
+
+ ///
+ /// Gets or sets the message.
+ ///
+ ///
+ /// The message.
+ ///
+ public string Message { get; set; }
+ }
+}
diff --git a/MyFinance.Service/MyFinance.Service.csproj b/EFMVC.Core/EFMVC.Core.csproj
similarity index 68%
rename from MyFinance.Service/MyFinance.Service.csproj
rename to EFMVC.Core/EFMVC.Core.csproj
index 315c78b..1e5bcf9 100644
--- a/MyFinance.Service/MyFinance.Service.csproj
+++ b/EFMVC.Core/EFMVC.Core.csproj
@@ -5,21 +5,14 @@
AnyCPU
8.0.30703
2.0
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}
Library
Properties
- MyFinance.Service
- MyFinance.Service
- v4.0
+ EFMVC.Core
+ EFMVC.Core
+ v4.5
512
-
-
-
-
-
-
-
-
+
true
@@ -29,6 +22,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -37,6 +31,7 @@
TRACE
prompt
4
+ false
@@ -48,21 +43,11 @@
-
-
+
+
-
-
-
-
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}
- MyFinance.Data
-
-
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}
- MyFinance.Domain
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EFMVC.Data/Configurations/CategoryConfiguration.cs b/EFMVC.Data/Configurations/CategoryConfiguration.cs
new file mode 100644
index 0000000..0fbabe2
--- /dev/null
+++ b/EFMVC.Data/Configurations/CategoryConfiguration.cs
@@ -0,0 +1,19 @@
+using EFMVC.Model;
+using System;
+using System.Collections.Generic;
+using System.Data.Entity.ModelConfiguration;
+using System.Linq;
+using System.Text;
+
+namespace EFMVC.Data.Configurations
+{
+ public class CategoryConfiguration : EntityTypeConfiguration
+ {
+ public CategoryConfiguration()
+ {
+ ToTable("Categories");
+ Property(c => c.Name).HasMaxLength(50).IsRequired();
+ Property(c => c.Description).HasMaxLength(140);
+ }
+ }
+}
diff --git a/EFMVC.Data/Configurations/ExpenseConfiguration.cs b/EFMVC.Data/Configurations/ExpenseConfiguration.cs
new file mode 100644
index 0000000..8668f31
--- /dev/null
+++ b/EFMVC.Data/Configurations/ExpenseConfiguration.cs
@@ -0,0 +1,22 @@
+using EFMVC.Model;
+using System;
+using System.Collections.Generic;
+using System.Data.Entity.ModelConfiguration;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EFMVC.Data.Configurations
+{
+ public class ExpenseConfiguration : EntityTypeConfiguration
+ {
+ public ExpenseConfiguration()
+ {
+ ToTable("Expenses");
+ Property(e => e.Transaction).HasMaxLength(100).IsRequired();
+ Property(e => e.Date).IsRequired();
+ Property(e => e.Amount).IsRequired();
+ Property(e => e.CategoryId).IsRequired();
+ }
+ }
+}
diff --git a/MyFinance.Data/MyFinance.Data.csproj b/EFMVC.Data/EFMVC.Data.csproj
similarity index 64%
rename from MyFinance.Data/MyFinance.Data.csproj
rename to EFMVC.Data/EFMVC.Data.csproj
index 0a347ff..5519103 100644
--- a/MyFinance.Data/MyFinance.Data.csproj
+++ b/EFMVC.Data/EFMVC.Data.csproj
@@ -5,21 +5,14 @@
AnyCPU
8.0.30703
2.0
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}
Library
Properties
- MyFinance.Data
- MyFinance.Data
- v4.0
+ EFMVC.Data
+ EFMVC.Data
+ v4.5
512
-
-
-
-
-
-
-
-
+
true
@@ -29,6 +22,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -37,13 +31,15 @@
TRACE
prompt
4
+ false
-
+
False
- ..\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll
+ ..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll
+
@@ -53,6 +49,8 @@
+
+
@@ -61,20 +59,34 @@
-
+
+
+
+ 201212011507315_InitialCreate.cs
+
+
-
-
+
-
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}
- MyFinance.Domain
+
+ Designer
+
+
+
+
+
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}
+ EFMVC.Model
-
+
+
+ 201212011507315_InitialCreate.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ H4sIAAAAAAAEANVawXLbNhC9d6b/wOGp7UxMO+khzUjJOLLdehrbGcvJNQOTKxlTEGAB0JW+rYd+Un+hC1IkQYKUSMqKm4tHArAPi8Xbxe7K//79z+TdKmbeI0hFBZ/6J0fHvgc8FBHly6mf6sWL1/67t99/NzmP4pX3uVj3yqxDSa6m/oPWyZsgUOEDxEQdxTSUQomFPgpFHJBIBC+Pj38JTk4CQAgfsTxvcptyTWPIvuDXmeAhJDol7EpEwNRmHGfmGap3TWJQCQlh6p9fXH2eHZ0RTXzvlFGCGsyBLXwv+fnNJwVzLQVfzhOiKWF36wRwfkGYgo2+b5Kf+6p8/NKoHBDOhUY4wUcd2S8Pg8c5x2PrtVErO9LUnxENSyHX9ipc9zusawM49FGKBKRe38KiIXsZ+V5Qlw+aAKV4i6xRZ+pfcv3qpe9dp4yRewal1dCscy0k/AocJEpFH4nWIJEElxFkx3F2b+xl/ha74PUgs3zvgq4g+gB8qR/Kna7IqhjBj773iVMkIgppmUKLZtt3PQMVSprk9/aEm+ffG3tfk0e6zDjS0OJ8lQBXoHzvFli2QD3QJKfs0WbyS0kC70KK+FawSrCc+3JH5BI0HkV0LJiLVIYN1SZBxbitPNygjaHhRnQMCy3RQ5PwThKuSPjkdOjHRVS52NV8vqPxcJDTWGDULGFEiqKDQfr7fV+GV+Tdl+EFgTsZXrjAKIbj2yDH0NvIjeF2IXdoYp/HhLKvT+kLKpV+nsj+gTzXzh+JUn8JGf1G1MPhH5WWIDKTYEiydywxJvwglpTn0t1ofRQ7xaj6aKv1XqD/Ej5YK+P2wwJTl/efKiVCmkWj+lPzpSPhOueRtyss5ddthTW84JRpmjAaog5T/yfngFtgy/e8gq2iZB33xG+GqRt+Bgw0eKfZi2aisApJ5FoY7RPVRzCygTShhTBMu5WWhHLthkHKQ5oQtkP7htzANNXoV+7UnDkD3NLEwB33sr8K5U4N0+2y1CSwaOa+PSijUQJkwUBTuJi6xUzAyiGgkZmDrqtMTepYcdwhisO3OkqVfjoYJYd3QJh3rE0+e0+bwpZBHCWsJMBa1pUoNG+ph4OWmtvndq67h0taQPY1NF2rftiWqFQyoKpng7ygLQrfoKPynVyRJMFnxaqENyPePC+DZy/mw8vROMcIQtVSlZbaljthYkKW0JjFrVHT7Pk3ZL4nhkOzKHaW9eR7sZtDe/fiCgYWIuaz5VtZU+Coi0GVCS/wVLEJLFnm5V52i2jWiSCMyC3p9EywNOa7A043Wp7U2Dj5SH+EWtFrA9UmXLxJ0LCNEyQd6zvvTP0+e9126aYj77q1au111Z2SXZa1SlXbrp3F7zasWi1qo9UmBtx6Vl7Wrjsb6Y9Q1JY2RjHWH2WcNzwT9/J3bSTx3GIyk97FunaxLnMWFaRtyvZqdBvKpj6skTYf6o9hFXs2jjXcH6uq3myoarQ/Ur0as9HqM8McqSyxmv5UTgw7q1VmNQ9sTQ1w1araqnlrNdwfqyi4bKBi7Cs7qpMzNZeUu5e5UyNHmmzyld0/ITgJTL7E99A8jzQyyct8rTTEubPP/2QzRsHEwmLBFeF0AUrfiT8AU1jMr143fo0Y8UtBoFTEvpWfC6gxx87W1cAGgN3V4Y9Ehg9E/hCT1Y9P0f3vBHR7HN9a2/wgl9HSMd/zTqwueISf9f5d8AUTRD9BEzwz4KhO0/+sz3wQJtRazPtxwGkb7wfXbAXvh9bW3h0QNXq1bEcTv7Vl24Y2qmV7T4e7Ub1dO96F9mjWVi2lr91GddpI4xrEo7qxW1och26/fjvtVrdL1avhut7abs0TRfS7e4H3nTN9S4uwox27rRvbtkNXN7O1V9vZqm1D3jR3n6GL2zR3vQHXo23b1u89TI/WrSuQrNY/MKGvKLqsIMy/M3EIazQt11zyhSg8pqFRsaQRZq9AE4zz5FRqusB8DKdDUCr70fEzYWn2QN9DdMlvUp2kGo8M8T2rGdF43bb9s0Z0XefJTZY9q6c4AqpJzVN1w9+nlEWl3hctj0QHhHHnTUpj7lKb1Ga5LpGuBe8JtDFfGYXuIE4YgqkbPieP0K3bbhvWLTY5o2QpSaw2GJU8fkX6RfHq7X/TVjAcgicAAA==
+
+
\ No newline at end of file
diff --git a/EFMVC.Data/Migrations/Configuration.cs b/EFMVC.Data/Migrations/Configuration.cs
new file mode 100644
index 0000000..74bdd01
--- /dev/null
+++ b/EFMVC.Data/Migrations/Configuration.cs
@@ -0,0 +1,31 @@
+namespace EFMVC.Data.Migrations
+{
+ using System;
+ using System.Data.Entity;
+ using System.Data.Entity.Migrations;
+ using System.Linq;
+
+ internal sealed class Configuration : DbMigrationsConfiguration
+ {
+ public Configuration()
+ {
+ AutomaticMigrationsEnabled = false;
+ }
+
+ protected override void Seed(EFMVC.Data.EFMVCDataContex context)
+ {
+ // This method will be called after migrating to the latest version.
+
+ // You can use the DbSet.AddOrUpdate() helper extension method
+ // to avoid creating duplicate seed data. E.g.
+ //
+ // context.People.AddOrUpdate(
+ // p => p.FullName,
+ // new Person { FullName = "Andrew Peters" },
+ // new Person { FullName = "Brice Lambson" },
+ // new Person { FullName = "Rowan Miller" }
+ // );
+ //
+ }
+ }
+}
diff --git a/MyFinance.Domain/Properties/AssemblyInfo.cs b/EFMVC.Data/Properties/AssemblyInfo.cs
similarity index 89%
rename from MyFinance.Domain/Properties/AssemblyInfo.cs
rename to EFMVC.Data/Properties/AssemblyInfo.cs
index 678440b..a9b58c5 100644
--- a/MyFinance.Domain/Properties/AssemblyInfo.cs
+++ b/EFMVC.Data/Properties/AssemblyInfo.cs
@@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("MyFinance.Domain")]
+[assembly: AssemblyTitle("EFMVC.Data")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("MyFinance.Domain")]
+[assembly: AssemblyProduct("EFMVC.Data")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -20,7 +20,7 @@
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("d257782d-d26a-4495-a35e-c7c336e72872")]
+[assembly: Guid("219579f5-a96e-4057-acda-4c5fdf98b5cf")]
// Version information for an assembly consists of the following four values:
//
diff --git a/EFMVC.Data/Repositories/CategoryRepository.cs b/EFMVC.Data/Repositories/CategoryRepository.cs
new file mode 100644
index 0000000..5dba65b
--- /dev/null
+++ b/EFMVC.Data/Repositories/CategoryRepository.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
+namespace EFMVC.Data.Repositories
+{
+ public class CategoryRepository: RepositoryBase, ICategoryRepository
+ {
+ public CategoryRepository(IDatabaseFactory databaseFactory)
+ : base(databaseFactory)
+ {
+ }
+ public IEnumerable GetCategoryWithExpenses()
+ {
+ var category= this.GetAll().Join(this.DataContext.Expenses, c => c.CategoryId, e => e.CategoryId, (c, e) => new { c, e })
+ .GroupBy(z => new { z.c.CategoryId, z.c.Name,z.c.Description }, z => z.e)
+ .Select(g => new CategoryWithExpense { CategoryId = g.Key.CategoryId, CategoryName = g.Key.Name,Description=g.Key.Description, TotalExpenses = g.Sum(s => s.Amount) });
+ return category;
+ }
+ }
+ public interface ICategoryRepository : IRepository
+ {
+ IEnumerable GetCategoryWithExpenses();
+ }
+ public class CategoryWithExpense
+ {
+ public int CategoryId { get; set; }
+ public string CategoryName { get; set; }
+ public string Description { get; set; }
+ public double TotalExpenses { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MyFinance.Data/Repositories/ExpenseRepository.cs b/EFMVC.Data/Repositories/ExpenseCategory.cs
similarity index 74%
rename from MyFinance.Data/Repositories/ExpenseRepository.cs
rename to EFMVC.Data/Repositories/ExpenseCategory.cs
index ef0b883..f69da62 100644
--- a/MyFinance.Data/Repositories/ExpenseRepository.cs
+++ b/EFMVC.Data/Repositories/ExpenseCategory.cs
@@ -2,18 +2,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
-namespace MyFinance.Data
+namespace EFMVC.Data.Repositories
{
public class ExpenseRepository : RepositoryBase, IExpenseRepository
- {
+ {
public ExpenseRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
- {
- }
+ {
}
+ }
public interface IExpenseRepository : IRepository
{
}
diff --git a/EFMVC.Data/Repositories/UserRepository.cs b/EFMVC.Data/Repositories/UserRepository.cs
new file mode 100644
index 0000000..9253ea8
--- /dev/null
+++ b/EFMVC.Data/Repositories/UserRepository.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
+
+namespace EFMVC.Data.Repositories
+{
+ public class UserRepository : RepositoryBase, IUserRepository
+ {
+ public UserRepository(IDatabaseFactory databaseFactory)
+ : base(databaseFactory)
+ {
+ }
+ }
+ public interface IUserRepository : IRepository
+ {
+ }
+}
diff --git a/EFMVC.Data/packages.config b/EFMVC.Data/packages.config
new file mode 100644
index 0000000..8707e72
--- /dev/null
+++ b/EFMVC.Data/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Domain/Commands/Category/CreateOrUpdateCategoryCommand.cs b/EFMVC.Domain/Commands/Category/CreateOrUpdateCategoryCommand.cs
new file mode 100644
index 0000000..fc8da34
--- /dev/null
+++ b/EFMVC.Domain/Commands/Category/CreateOrUpdateCategoryCommand.cs
@@ -0,0 +1,17 @@
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class CreateOrUpdateCategoryCommand : ICommand
+ {
+ public CreateOrUpdateCategoryCommand(int CategoryId,string name, string description)
+ {
+ this.CategoryId = CategoryId;
+ this.Name = name;
+ this.Description = description;
+ }
+ public int CategoryId { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/Commands/Category/DeleteCategoryCommand.cs b/EFMVC.Domain/Commands/Category/DeleteCategoryCommand.cs
new file mode 100644
index 0000000..273510d
--- /dev/null
+++ b/EFMVC.Domain/Commands/Category/DeleteCategoryCommand.cs
@@ -0,0 +1,9 @@
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class DeleteCategoryCommand : ICommand
+ {
+ public int CategoryId { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/Commands/Expense/CreateOrUpdateExpenseCommand.cs b/EFMVC.Domain/Commands/Expense/CreateOrUpdateExpenseCommand.cs
new file mode 100644
index 0000000..ae71495
--- /dev/null
+++ b/EFMVC.Domain/Commands/Expense/CreateOrUpdateExpenseCommand.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class CreateOrUpdateExpenseCommand : ICommand
+ {
+ public int ExpenseId { get; set; }
+ public int CategoryId { get; set; }
+ public string Transaction { get; set; }
+ public DateTime Date { get; set; }
+ public double Amount { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/Commands/Expense/DeleteExpenseCommand.cs b/EFMVC.Domain/Commands/Expense/DeleteExpenseCommand.cs
new file mode 100644
index 0000000..0bdeea4
--- /dev/null
+++ b/EFMVC.Domain/Commands/Expense/DeleteExpenseCommand.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class DeleteExpenseCommand : ICommand
+ {
+ public int ExpenseId { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/Commands/Security/ChangePasswordCommand.cs b/EFMVC.Domain/Commands/Security/ChangePasswordCommand.cs
new file mode 100644
index 0000000..3febe4b
--- /dev/null
+++ b/EFMVC.Domain/Commands/Security/ChangePasswordCommand.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class ChangePasswordCommand : ICommand
+ {
+ public int UserId { get; set; }
+ public string OldPassword { get; set; }
+ public string NewPassword { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/Commands/Security/UserRegisterCommand.cs b/EFMVC.Domain/Commands/Security/UserRegisterCommand.cs
new file mode 100644
index 0000000..a94bde5
--- /dev/null
+++ b/EFMVC.Domain/Commands/Security/UserRegisterCommand.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+
+namespace EFMVC.Domain.Commands
+{
+ public class UserRegisterCommand : ICommand
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string Email { get; set; }
+ public string Password { get; set; }
+ public int RoleId { get; set; }
+ public bool Activated { get; set; }
+ }
+}
diff --git a/EFMVC.Domain/EFMVC.Domain.csproj b/EFMVC.Domain/EFMVC.Domain.csproj
new file mode 100644
index 0000000..e115f82
--- /dev/null
+++ b/EFMVC.Domain/EFMVC.Domain.csproj
@@ -0,0 +1,104 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}
+ Library
+ Properties
+ EFMVC.Domain
+ EFMVC.Domain
+ v4.5
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+
+
+ {955FD94A-BBC1-4469-889A-740FB98338DE}
+ EFMVC.CommandProcessor
+
+
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}
+ EFMVC.Core
+
+
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}
+ EFMVC.Data
+
+
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}
+ EFMVC.Model
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Domain/Handlers/Category/CanAddCategory.cs b/EFMVC.Domain/Handlers/Category/CanAddCategory.cs
new file mode 100644
index 0000000..771d6b6
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Category/CanAddCategory.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using EFMVC.Core.Common;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
+using EFMVC.Domain.Properties;
+namespace EFMVC.Domain.Handlers
+{
+ public class CanAddCategory : IValidationHandler
+ {
+ private readonly ICategoryRepository categoryRepository;
+ public CanAddCategory(ICategoryRepository categoryRepository, IUnitOfWork unitOfWork)
+ {
+ this.categoryRepository = categoryRepository;
+ }
+ public IEnumerable Validate(CreateOrUpdateCategoryCommand command)
+ {
+ Category isCategoryExists=null;
+ if(command.CategoryId==0)
+ isCategoryExists = categoryRepository.Get(c => c.Name == command.Name);
+ else
+ isCategoryExists = categoryRepository.Get(c => c.Name == command.Name && c.CategoryId!=command.CategoryId);
+ if (isCategoryExists!=null )
+ {
+ yield return new ValidationResult("Name", Resources.CategoryExists);
+ }
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Category/CreateOrUpdateCategoryHandler.cs b/EFMVC.Domain/Handlers/Category/CreateOrUpdateCategoryHandler.cs
new file mode 100644
index 0000000..a45d833
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Category/CreateOrUpdateCategoryHandler.cs
@@ -0,0 +1,34 @@
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Domain.Commands;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Model;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class CreateOrUpdateCategoryHandler : ICommandHandler
+ {
+ private readonly ICategoryRepository categoryRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public CreateOrUpdateCategoryHandler(ICategoryRepository categoryRepository, IUnitOfWork unitOfWork)
+ {
+ this.categoryRepository = categoryRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(CreateOrUpdateCategoryCommand command)
+ {
+ var category = new Category
+ {
+ CategoryId = command.CategoryId,
+ Name = command.Name,
+ Description = command.Description
+ };
+ if (category.CategoryId == 0)
+ categoryRepository.Add(category);
+ else
+ categoryRepository.Update(category);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Category/DeleteCategoryHandler.cs b/EFMVC.Domain/Handlers/Category/DeleteCategoryHandler.cs
new file mode 100644
index 0000000..fa1036d
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Category/DeleteCategoryHandler.cs
@@ -0,0 +1,25 @@
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class DeleteCategoryHandler : ICommandHandler
+ {
+ private readonly ICategoryRepository categoryRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public DeleteCategoryHandler(ICategoryRepository categoryRepository, IUnitOfWork unitOfWork)
+ {
+ this.categoryRepository = categoryRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(DeleteCategoryCommand command)
+ {
+ var category = categoryRepository.GetById(command.CategoryId);
+ categoryRepository.Delete(category);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Expense/CreateOrUpdateExpenseHandler.cs b/EFMVC.Domain/Handlers/Expense/CreateOrUpdateExpenseHandler.cs
new file mode 100644
index 0000000..7909e86
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Expense/CreateOrUpdateExpenseHandler.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class CreateOrUpdateExpenseHandler : ICommandHandler
+ {
+ private readonly IExpenseRepository expenseRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public CreateOrUpdateExpenseHandler(IExpenseRepository expenseRepository, IUnitOfWork unitOfWork)
+ {
+ this.expenseRepository = expenseRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(CreateOrUpdateExpenseCommand command)
+ {
+ var expense = new Expense
+ {
+ ExpenseId =command.ExpenseId,
+ CategoryId = command.CategoryId,
+ Amount = command.Amount,
+ Date=command.Date,
+ Transaction=command.Transaction
+ };
+ if (expense.ExpenseId == 0)
+ expenseRepository.Add(expense);
+ else
+ expenseRepository.Update(expense);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Expense/DeleteExpenseHandler.cs b/EFMVC.Domain/Handlers/Expense/DeleteExpenseHandler.cs
new file mode 100644
index 0000000..8c7e777
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Expense/DeleteExpenseHandler.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.Domain.Commands;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class DeleteExpenseHandler : ICommandHandler
+ {
+ private readonly IExpenseRepository expenseRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public DeleteExpenseHandler(IExpenseRepository expenseRepository, IUnitOfWork unitOfWork)
+ {
+ this.expenseRepository = expenseRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(DeleteExpenseCommand command)
+ {
+ var expense = expenseRepository.GetById(command.ExpenseId);
+ expenseRepository.Delete(expense);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Security/CanAddUser.cs b/EFMVC.Domain/Handlers/Security/CanAddUser.cs
new file mode 100644
index 0000000..14d0d16
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Security/CanAddUser.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.Domain.Commands;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Data.Repositories;
+using EFMVC.Core.Common;
+using EFMVC.Model;
+using EFMVC.Domain.Properties;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class CanAddUser : IValidationHandler
+ {
+ private readonly IUserRepository userRepository;
+ public CanAddUser(IUserRepository userRepository)
+ {
+ this.userRepository = userRepository;
+ }
+ public IEnumerable Validate(UserRegisterCommand command)
+ {
+ User isUserExists = null;
+ isUserExists = userRepository.Get(c => c.Email == command.Email);
+
+ if (isUserExists != null)
+ {
+ yield return new ValidationResult("EMail", Resources.UserExists);
+ }
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Security/CanChangePassword.cs b/EFMVC.Domain/Handlers/Security/CanChangePassword.cs
new file mode 100644
index 0000000..a76f85b
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Security/CanChangePassword.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.Data.Repositories;
+using EFMVC.Core.Common;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Model;
+using EFMVC.Domain.Commands;
+using EFMVC.Domain.Properties;
+
+namespace EFMVC.Domain.Handlers
+{
+ public class CanChangePassword : IValidationHandler
+ {
+ private readonly IUserRepository userRepository;
+ public CanChangePassword(IUserRepository userRepository)
+ {
+ this.userRepository = userRepository;
+ }
+ public IEnumerable Validate(ChangePasswordCommand command)
+ {
+ User user = userRepository.GetById(command.UserId);
+ var encoded = Md5Encrypt.Md5EncryptPassword(command.OldPassword);
+
+ if (!user.PasswordHash.Equals(encoded))
+ {
+ yield return new ValidationResult("OldPassword", Resources.Password);
+ }
+ }
+ }
+}
diff --git a/EFMVC.Domain/Handlers/Security/ChangePasswordHandler.cs b/EFMVC.Domain/Handlers/Security/ChangePasswordHandler.cs
new file mode 100644
index 0000000..6305f7f
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Security/ChangePasswordHandler.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Model;
+using EFMVC.Domain.Commands;
+
+namespace EFMVC.Domain.Handlers.Security
+{
+ public class ChangePasswordHandler: ICommandHandler
+ {
+ private readonly IUserRepository userRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public ChangePasswordHandler(IUserRepository userRepository, IUnitOfWork unitOfWork)
+ {
+ this.userRepository = userRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(ChangePasswordCommand command)
+ {
+ var user = userRepository.GetById(command.UserId);
+ user.Password = command.NewPassword;
+ userRepository.Update(user);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
+
diff --git a/EFMVC.Domain/Handlers/Security/UserRegisterHandler.cs b/EFMVC.Domain/Handlers/Security/UserRegisterHandler.cs
new file mode 100644
index 0000000..faa8ddc
--- /dev/null
+++ b/EFMVC.Domain/Handlers/Security/UserRegisterHandler.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using EFMVC.Data.Repositories;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Model;
+namespace EFMVC.Domain.Handlers.Security
+{
+ public class UserRegisterHandler : ICommandHandler
+ {
+ private readonly IUserRepository userRepository;
+ private readonly IUnitOfWork unitOfWork;
+ public UserRegisterHandler(IUserRepository userRepository, IUnitOfWork unitOfWork)
+ {
+ this.userRepository = userRepository;
+ this.unitOfWork = unitOfWork;
+ }
+ public ICommandResult Execute(UserRegisterCommand command)
+ {
+ var user = new User
+ {
+ FirstName = command.FirstName,
+ LastName = command.LastName,
+ Email = command.Email,
+ Password = command.Password,
+ RoleId = command.RoleId,
+ DateCreated=DateTime.Now,
+ LastLoginTime=DateTime.Now,
+ Activated = command.Activated
+ };
+ userRepository.Add(user);
+ unitOfWork.Commit();
+ return new CommandResult(true);
+ }
+ }
+}
diff --git a/MyFinance.Service/Properties/AssemblyInfo.cs b/EFMVC.Domain/Properties/AssemblyInfo.cs
similarity index 89%
rename from MyFinance.Service/Properties/AssemblyInfo.cs
rename to EFMVC.Domain/Properties/AssemblyInfo.cs
index 80b4a5d..31f0bb7 100644
--- a/MyFinance.Service/Properties/AssemblyInfo.cs
+++ b/EFMVC.Domain/Properties/AssemblyInfo.cs
@@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("MyFinance.Service")]
+[assembly: AssemblyTitle("EFMVC.Domain")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("MyFinance.Service")]
+[assembly: AssemblyProduct("EFMVC.Domain")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -20,7 +20,7 @@
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("0e68971b-c016-4147-a152-8771d421ae79")]
+[assembly: Guid("bc5319eb-7a07-4e2f-bdf8-0ecc2b7e7945")]
// Version information for an assembly consists of the following four values:
//
diff --git a/EFMVC.Domain/Properties/Resources.Designer.cs b/EFMVC.Domain/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..afd909c
--- /dev/null
+++ b/EFMVC.Domain/Properties/Resources.Designer.cs
@@ -0,0 +1,90 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace EFMVC.Domain.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EFMVC.Domain.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Category is exists.
+ ///
+ internal static string CategoryExists {
+ get {
+ return ResourceManager.GetString("CategoryExists", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The current password is incorrect.
+ ///
+ internal static string Password {
+ get {
+ return ResourceManager.GetString("Password", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Email Id is exists.
+ ///
+ internal static string UserExists {
+ get {
+ return ResourceManager.GetString("UserExists", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/EFMVC.Domain/Properties/Resources.resx b/EFMVC.Domain/Properties/Resources.resx
new file mode 100644
index 0000000..9bee869
--- /dev/null
+++ b/EFMVC.Domain/Properties/Resources.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Category is exists
+
+
+ The current password is incorrect
+
+
+ Email Id is exists
+
+
\ No newline at end of file
diff --git a/EFMVC.Model/App.config b/EFMVC.Model/App.config
new file mode 100644
index 0000000..2a0cf8a
--- /dev/null
+++ b/EFMVC.Model/App.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/MyFinance.Domain/MyFinance.Domain.csproj b/EFMVC.Model/EFMVC.Model.csproj
similarity index 76%
rename from MyFinance.Domain/MyFinance.Domain.csproj
rename to EFMVC.Model/EFMVC.Model.csproj
index 0993ca4..3d736a4 100644
--- a/MyFinance.Domain/MyFinance.Domain.csproj
+++ b/EFMVC.Model/EFMVC.Model.csproj
@@ -5,21 +5,14 @@
AnyCPU
8.0.30703
2.0
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}
Library
Properties
- MyFinance.Domain
- MyFinance.Domain
- v4.0
+ EFMVC.Model
+ EFMVC.Model
+ v4.5
512
-
-
-
-
-
-
-
-
+
true
@@ -29,6 +22,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -37,12 +31,9 @@
TRACE
prompt
4
+ false
-
- False
- ..\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll
-
@@ -56,11 +47,17 @@
-
+
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}
+ EFMVC.Core
+
+
+
+
diff --git a/EFMVC.Model/Entities/Category.cs b/EFMVC.Model/Entities/Category.cs
new file mode 100644
index 0000000..4182c4e
--- /dev/null
+++ b/EFMVC.Model/Entities/Category.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.ComponentModel.DataAnnotations;
+
+namespace EFMVC.Model
+{
+ public class Category
+ {
+
+ public int CategoryId { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public virtual ICollection Expenses { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Model/Entities/Expense.cs b/EFMVC.Model/Entities/Expense.cs
new file mode 100644
index 0000000..f8f68e6
--- /dev/null
+++ b/EFMVC.Model/Entities/Expense.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel.DataAnnotations;
+
+namespace EFMVC.Model
+{
+ public class Expense
+ {
+ public int ExpenseId { get; set; }
+ public string Transaction { get; set; }
+ public DateTime Date { get; set; }
+ public double Amount { get; set; }
+ public int CategoryId { get; set; }
+ public virtual Category Category { get; set; }
+ }
+}
diff --git a/EFMVC.Model/Entities/User.cs b/EFMVC.Model/Entities/User.cs
new file mode 100644
index 0000000..17e8bbc
--- /dev/null
+++ b/EFMVC.Model/Entities/User.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel.DataAnnotations;
+using EFMVC.Core.Common;
+
+namespace EFMVC.Model
+{
+ public class User
+ {
+ public User()
+ {
+ DateCreated = DateTime.Now;
+ }
+
+ [Key]
+ public int UserId { get; set; }
+ [Required]
+ public string Email { get; set; }
+ [Required]
+ public string FirstName { get; set; }
+ [Required]
+ public string LastName { get; set; }
+ public string PasswordHash { get; set; }
+ public DateTime DateCreated { get; set; }
+ public DateTime? LastLoginTime { get; set; }
+ public bool Activated { get; set; }
+ public int RoleId { get; set; }
+
+ public string Password
+ {
+ set { PasswordHash = Md5Encrypt.Md5EncryptPassword(value); }
+ }
+ internal static string GenerateRandomString()
+ {
+ var builder = new StringBuilder();
+ var random = new Random();
+ for (int i = 0; i < 6; i++)
+ {
+ char ch = Convert.ToChar(Convert.ToInt32(Math.Floor(25 * random.NextDouble() + 75)));
+ builder.Append(ch);
+ }
+ return builder.ToString();
+ }
+
+ public string ResetPassword()
+ {
+ var newPass = GenerateRandomString();
+ Password = newPass;
+ return newPass;
+ }
+ public string DisplayName
+ {
+ get { return FirstName; }
+ }
+ }
+}
diff --git a/EFMVC.Model/Properties/AssemblyInfo.cs b/EFMVC.Model/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..53c8b17
--- /dev/null
+++ b/EFMVC.Model/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("EFMVC.Model")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("EFMVC.Model")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("35dc60bd-cbf3-4302-b6e2-49134b230a37")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MyFinance.Domain/packages.config b/EFMVC.Model/packages.config
similarity index 55%
rename from MyFinance.Domain/packages.config
rename to EFMVC.Model/packages.config
index 058af18..a514313 100644
--- a/MyFinance.Domain/packages.config
+++ b/EFMVC.Model/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/EFMVC.Tests/ApiControllers/CategoryApiControllerTest.cs b/EFMVC.Tests/ApiControllers/CategoryApiControllerTest.cs
new file mode 100644
index 0000000..a3bc80e
--- /dev/null
+++ b/EFMVC.Tests/ApiControllers/CategoryApiControllerTest.cs
@@ -0,0 +1,205 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Web.Http.Hosting;
+using System.Web.Http;
+using System.Web.Http.Routing;
+using NUnit.Framework;
+using Moq;
+using EFMVC.Data.Repositories;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Web.ViewModels;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using AutoMapper;
+using EFMVC.Web.API.Controllers;
+using Newtonsoft.Json;
+using EFMVC.Web.API.Models;
+using EFMVC.Web.API;
+
+namespace EFMVC.Tests.ApiControllers
+{
+ [TestFixture]
+ public class CategoryApiControllerTest
+ {
+ private Mock categoryRepository;
+ private Mock commandBus;
+ [SetUp]
+ public void SetUp()
+ {
+ categoryRepository = new Mock();
+ commandBus = new Mock();
+ }
+ [Test]
+ public void Get_All_Returns_AllCategory()
+ {
+ // Arrange
+ IEnumerable fakeCategories = GetCategories();
+ categoryRepository.Setup(x => x.GetCategoryWithExpenses()).Returns(fakeCategories);
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage()
+ {
+ Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }
+ }
+ };
+ // Act
+ var categories = controller.Get();
+ // Assert
+ Assert.IsNotNull(categories, "Result is null");
+ Assert.IsInstanceOf(typeof(IEnumerable),categories, "Wrong Model");
+ Assert.AreEqual(3, categories.Count(), "Got wrong number of Categories");
+ }
+ [Test]
+ public void Get_CorrectCategoryId_Returns_Category()
+ {
+ // Arrange
+ IEnumerable fakeCategories = GetCategories();
+ categoryRepository.Setup(x => x.GetCategoryWithExpenses()).Returns(fakeCategories);
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage()
+ {
+ Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }
+ }
+ };
+ // Act
+ var response = controller.Get(1);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ var category = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
+ Assert.AreEqual(1, category.CategoryId, "Got wrong number of Categories");
+ }
+ [Test]
+ public void Get_InValidCategoryId_Returns_NotFound()
+ {
+ // Arrange
+ IEnumerable fakeCategories = GetCategories();
+ categoryRepository.Setup(x => x.GetCategoryWithExpenses()).Returns(fakeCategories);
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage()
+ {
+ Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }
+ }
+ };
+ // Act
+ var response = controller.Get(5);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
+
+ }
+ [Test]
+ public void Post_Category_Returns_CreatedStatusCode()
+ {
+ // Arrange
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ Mapper.CreateMap();
+ var httpConfiguration = new HttpConfiguration();
+ WebApiConfig.Register(httpConfiguration);
+ var httpRouteData = new HttpRouteData(httpConfiguration.Routes["DefaultApi"],
+ new HttpRouteValueDictionary { { "controller", "category" } });
+ var controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/category/")
+ {
+ Properties =
+ {
+ { HttpPropertyKeys.HttpConfigurationKey, httpConfiguration },
+ { HttpPropertyKeys.HttpRouteDataKey, httpRouteData }
+ }
+ }
+ };
+ // Act
+ CategoryModel category = new CategoryModel();
+ category.CategoryId = 1;
+ category.CategoryName = "Mock Category";
+ var response = controller.Post(category);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
+ var newCategory = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
+ Assert.AreEqual(string.Format("http://localhost/api/category/{0}", newCategory.CategoryId), response.Headers.Location.ToString());
+ }
+ [Test]
+ public void Post_EmptyCategory_Returns_BadRequestStatusCode()
+ {
+ // Arrange
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ Mapper.CreateMap();
+ var httpConfiguration = new HttpConfiguration();
+ WebApiConfig.Register(httpConfiguration);
+ var httpRouteData = new HttpRouteData(httpConfiguration.Routes["DefaultApi"],
+ new HttpRouteValueDictionary { { "controller", "category" } });
+ var controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/category/")
+ {
+ Properties =
+ {
+ { HttpPropertyKeys.HttpConfigurationKey, httpConfiguration },
+ { HttpPropertyKeys.HttpRouteDataKey, httpRouteData }
+ }
+ }
+ };
+ // Act
+ CategoryModel category = new CategoryModel();
+ category.CategoryId = 0;
+ category.CategoryName = "";
+ // The ASP.NET pipeline doesn't run, so validation don't run.
+ controller.ModelState.AddModelError("", "mock error message");
+ var response = controller.Post(category);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
+
+ }
+ [Test]
+ public void Put_Category_Returns_OKStatusCode()
+ {
+ // Arrange
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ Mapper.CreateMap();
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage()
+ {
+ Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }
+ }
+ };
+ // Act
+ CategoryModel category = new CategoryModel();
+ category.CategoryId = 1;
+ category.CategoryName = "Mock Category";
+ var response = controller.Put(category.CategoryId,category);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ }
+ [Test]
+ public void Delete_Category_Returns_NoContentStatusCode()
+ {
+ // Arrange
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object)
+ {
+ Request = new HttpRequestMessage()
+ {
+ Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }
+ }
+ };
+ // Act
+ var response = controller.Delete(1);
+ // Assert
+ Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode);
+
+ }
+ private static IEnumerable GetCategories()
+ {
+ IEnumerable fakeCategories = new List {
+ new CategoryWithExpense {CategoryId=1, CategoryName = "Test1", Description="Test1Desc", TotalExpenses=1000},
+ new CategoryWithExpense {CategoryId=2, CategoryName = "Test2", Description="Test2Desc",TotalExpenses=2000},
+ new CategoryWithExpense { CategoryId=3, CategoryName = "Test3", Description="Test3Desc",TotalExpenses=3000}
+ }.AsEnumerable();
+ return fakeCategories;
+ }
+ }
+}
diff --git a/EFMVC.Tests/App.config b/EFMVC.Tests/App.config
new file mode 100644
index 0000000..ca5c13c
--- /dev/null
+++ b/EFMVC.Tests/App.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Tests/Controllers/AccountControllerTest.cs b/EFMVC.Tests/Controllers/AccountControllerTest.cs
new file mode 100644
index 0000000..da844e1
--- /dev/null
+++ b/EFMVC.Tests/Controllers/AccountControllerTest.cs
@@ -0,0 +1,159 @@
+using AutoMapper;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Data.Repositories;
+using EFMVC.Domain.Commands;
+using EFMVC.Model;
+using EFMVC.Web;
+using EFMVC.Web.Controllers;
+using EFMVC.Web.Core.Authentication;
+using EFMVC.Web.ViewModels;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq.Expressions;
+using System.Security.Principal;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace EFMVC.Tests.Controllers
+{
+ [TestFixture]
+ public class AccountControllerTest
+ {
+ private Mock formsAuthentication;
+ private Mock commandBus;
+ private Mock userRepository;
+ [SetUp]
+ public void SetUp()
+ {
+ formsAuthentication = new Mock();
+ userRepository = new Mock();
+ commandBus = new Mock();
+ }
+ [Test]
+ public void Cannot_Login_With_Empty_UserCrdential()
+ {
+ //Arrange
+ LogOnFormModel logon = new LogOnFormModel();
+ logon.UserName = string.Empty;
+ logon.Password = string.Empty;
+ AccountController controller = new AccountController(commandBus.Object, userRepository.Object, formsAuthentication.Object);
+ // The MVC pipeline doesn't run, so binding and validation don't run.
+ controller.ModelState.AddModelError("", "UserName and Password Should Provide");
+ //Act
+ var result = controller.Login(logon, "http://localhost:50521") as ViewResult;
+ //Assert
+ Assert.AreEqual(false, result.ViewData.ModelState.IsValid);
+ Assert.AreEqual("Login", result.ViewName);
+ }
+ [Test]
+ public void Cannot_AjaxLogin_With_Empty_UserCrdential()
+ {
+ //Arrange
+ LogOnFormModel logon = new LogOnFormModel();
+ logon.UserName = string.Empty;
+ logon.Password = string.Empty;
+ AccountController controller = new AccountController(commandBus.Object, userRepository.Object, formsAuthentication.Object);
+ // The MVC pipeline doesn't run, so binding and validation don't run.
+ controller.ModelState.AddModelError("", "UserName and Password Should Provide");
+ //Act
+ var actual = controller.JsonLogin(logon, "http://localhost:50521");
+ //Assert
+ // Assert.IsInstanceOfType(typeof(JsonResult), actual, "Wrong Type");
+ var result = (JsonResult)actual;
+ bool success =
+ (bool)
+ (result.Data.GetType().GetProperty("success")).GetValue(result.Data, null);
+ Assert.AreEqual(false, success);
+ }
+ [Test]
+ public void Cannot_Login_With_Wrong_UserCrdential()
+ {
+ //Arrange
+ userRepository.Setup(x => x.Get(It.IsAny>>())).Returns((User)null);
+ LogOnFormModel logon = new LogOnFormModel();
+ logon.UserName = "wrongmail@something.com";
+ logon.Password = "password123";
+ AccountController controller = new AccountController(commandBus.Object, userRepository.Object, formsAuthentication.Object);
+ //Act
+ var result = controller.Login(logon, "http://localhost:50521") as ViewResult;
+ //Assert
+ Assert.AreEqual(false, result.ViewData.ModelState.IsValid);
+ Assert.AreEqual("Login", result.ViewName);
+ }
+ [Test]
+ public void Login_Success_Redirects_To_Home()
+ {
+ //Arrange
+ var routes = new RouteCollection();
+ MvcApplication.RegisterRoutes(routes);
+ var returnUrl = new Uri("http://efmvc.codeplex.com");
+
+ Mock request = new Mock();
+ Mock response = new Mock();
+ Mock context = new Mock();
+
+ context.SetupGet(x => x.Request).Returns(request.Object);
+ context.SetupGet(x => x.Response).Returns(response.Object);
+ request.Setup(x => x.Url).Returns(new Uri("http://localhost:50521"));
+ User user = new User()
+ {
+ Email = "shiju.varghese@gmail.com",
+ UserId = 1,
+ FirstName = "Shiju",
+ LastName = "Var",
+ DateCreated = DateTime.Now,
+ Password = "password123",
+ RoleId = 2
+ };
+ userRepository.Setup(x => x.Get(It.IsAny>>())).Returns(user);
+ LogOnFormModel logon = new LogOnFormModel();
+ logon.UserName = user.Email;
+ logon.Password = "password123";
+ AccountController controller = new AccountController(commandBus.Object, userRepository.Object, formsAuthentication.Object);
+ //Act
+ controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
+ controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
+ var actual = controller.Login(logon, returnUrl.AbsoluteUri);
+ //Assert
+ Assert.IsInstanceOfType(typeof(RedirectToRouteResult), actual ,"Wrong Type");
+ var result = (RedirectToRouteResult)actual;
+ Assert.AreEqual("Home", result.RouteValues["controller"]);
+ Assert.AreEqual("Index", result.RouteValues["action"]);
+ }
+ [Test]
+ public void User_Register_Redirects_To_Home()
+ {
+ //Arrange
+ User user = new User()
+ {
+ Email = "shiju.varghese@gmail.com",
+ UserId = 1,
+ FirstName="Shiju",
+ LastName="Var",
+ DateCreated=DateTime.Now,
+ Password = "password123",
+ RoleId = 2
+ };
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ userRepository.Setup(x => x.Get(It.IsAny>>())).Returns(user);
+ Mapper.CreateMap();
+ UserFormModel userForm = new UserFormModel
+ {
+ Email = "shiju.varghese@gmail.com",
+ FirstName = "Shiju",
+ LastName = "Var",
+ Password = "password123",
+ ConfirmPassword = "password123"
+ };
+ AccountController controller = new AccountController(commandBus.Object, userRepository.Object, formsAuthentication.Object);
+ // Act
+ var result= controller.Register(userForm) as RedirectToRouteResult;
+ // Assert
+ Assert.AreEqual("Home", result.RouteValues["controller"]);
+ Assert.AreEqual("Index", result.RouteValues["action"]);
+ }
+ }
+}
diff --git a/EFMVC.Tests/Controllers/CategoryControllerTest.cs b/EFMVC.Tests/Controllers/CategoryControllerTest.cs
new file mode 100644
index 0000000..6426e4e
--- /dev/null
+++ b/EFMVC.Tests/Controllers/CategoryControllerTest.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Web.Mvc;
+using NUnit.Framework;
+using Moq;
+using EFMVC.Data.Repositories;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Web.Controllers;
+using EFMVC.Model;
+using EFMVC.Web.ViewModels;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using AutoMapper;
+namespace EFMVC.Tests.Controllers
+{
+ [TestFixture]
+ public class CategoryControllerTest
+ {
+ private Mock categoryRepository;
+ private Mock commandBus;
+ [SetUp]
+ public void SetUp()
+ {
+ categoryRepository = new Mock();
+ commandBus = new Mock();
+ }
+ [Test]
+ public void Index_Returns_Category_List()
+ {
+ // Arrange
+ IEnumerable fakeCategories = new List {
+ new Category { Name = "Test1", Description="Test1Desc"},
+ new Category { Name = "Test2", Description="Test2Desc"},
+ new Category { Name = "Test3", Description="Test3Desc"}
+ }.AsEnumerable();
+ categoryRepository.Setup(x => x.GetAll()).Returns(fakeCategories);
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object);
+ // Act
+ ViewResult result = controller.Index() as ViewResult;
+ // Assert
+ Assert.IsNotNull(result, "View Result is null");
+ Assert.IsInstanceOf(typeof(IEnumerable),
+ result.ViewData.Model, "Wrong View Model");
+ var categories = result.ViewData.Model as IEnumerable;
+ Assert.AreEqual(3, categories.Count(), "Got wrong number of Categories");
+ }
+ [Test]
+ public void Cannot_Create_Empty_Category()
+ {
+ // Arrange
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object);
+ // The MVC pipeline doesn't run, so binding and validation don't run.
+ controller.ModelState.AddModelError("", "mock error message");
+ Mapper.CreateMap();
+ // Act
+ CategoryFormModel category = new CategoryFormModel();
+ category.CategoryId = 0;
+ category.Name = string.Empty;
+ var result = controller.Save(category) as ViewResult;
+ // Assert - check that we are passing an invalid model to the view
+ Assert.AreEqual(false, result.ViewData.ModelState.IsValid);
+ Assert.AreEqual("Create", result.ViewName);
+ }
+ [Test]
+ public void Create_Category_Redirects_To_Index()
+ {
+ // Arrange
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object);
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ // Act
+ CategoryFormModel category = new CategoryFormModel();
+ category.CategoryId = 0;
+ category.Name = "Mock Category";
+ Mapper.CreateMap();
+ var result = controller.Save(category) as RedirectToRouteResult;
+ // Assert
+ Assert.AreEqual("Index", result.RouteValues["action"]);
+ }
+ [Test]
+ public void Delete_Category_ReturnsPartial()
+ {
+ // Arrange
+ CategoryController controller = new CategoryController(commandBus.Object, categoryRepository.Object);
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ // Act
+ var result = controller.Delete(1) as PartialViewResult;
+ // Assert
+ Assert.IsInstanceOf(typeof(IEnumerable),
+ result.ViewData.Model, "Wrong View Model");
+ Assert.AreEqual("_CategoryList", result.ViewName);
+ }
+ }
+}
diff --git a/EFMVC.Tests/Controllers/ExpenseControllerTest.cs b/EFMVC.Tests/Controllers/ExpenseControllerTest.cs
new file mode 100644
index 0000000..4875c01
--- /dev/null
+++ b/EFMVC.Tests/Controllers/ExpenseControllerTest.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Web.Mvc;
+using NUnit.Framework;
+using Moq;
+using EFMVC.Data.Repositories;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Web.Controllers;
+using EFMVC.Model;
+using EFMVC.Web.ViewModels;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.Domain.Commands;
+using System.Linq.Expressions;
+using System.Web;
+using System.Web.Routing;
+using AutoMapper;
+
+namespace EFMVC.Tests.Controllers
+{
+ [TestFixture]
+ public class ExpenseControllerTest
+ {
+ private Mock categoryRepository;
+ private Mock commandBus;
+ private Mock expenseRepository;
+ [SetUp]
+ public void SetUp()
+ {
+ categoryRepository = new Mock();
+ expenseRepository = new Mock();
+ commandBus = new Mock();
+ }
+ [Test]
+ public void Index_AjaxRequest_Returns_Partial_With_Expense_List()
+ {
+ // Arrange
+ Mock request = new Mock();
+ Mock response = new Mock();
+ Mock context = new Mock();
+
+ context.Setup(c => c.Request).Returns(request.Object);
+ context.Setup(c => c.Response).Returns(response.Object);
+ request.Setup(req => req["X-Requested-With"]).Returns("XMLHttpRequest");
+
+ IEnumerable fakeExpenses = GetMockExpenses();
+ expenseRepository.Setup(x => x.GetMany(It.IsAny>>())).Returns(fakeExpenses);
+ ExpenseController controller = new ExpenseController(commandBus.Object, categoryRepository.Object,expenseRepository.Object);
+ controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
+ // Act
+ var result = controller.Index(null, null) as PartialViewResult;
+ // Assert
+ Assert.IsNotNull(result, "View Result is null");
+ Assert.AreEqual("_ExpenseList", result.ViewName);
+ Assert.IsInstanceOf(typeof(IEnumerable),
+ result.ViewData.Model, "Wrong View Model");
+ var expenses = result.ViewData.Model as IEnumerable;
+ Assert.AreEqual(3, expenses.Count(), "Got wrong number of Categories");
+ }
+ [Test]
+ public void Index_NormalRequest_Returns_Index_With_Expense_List()
+ {
+ // Arrange
+ Mock request = new Mock();
+ Mock response = new Mock();
+ Mock context = new Mock();
+
+ context.Setup(c => c.Request).Returns(request.Object);
+ context.Setup(c => c.Response).Returns(response.Object);
+
+ IEnumerable fakeExpenses = GetMockExpenses();
+
+ expenseRepository.Setup(x => x.GetMany(It.IsAny>>())).Returns(fakeExpenses);
+ ExpenseController controller = new ExpenseController(commandBus.Object, categoryRepository.Object, expenseRepository.Object);
+ controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
+ // Act
+ var result = controller.Index(null, null) as ViewResult;
+ // Assert
+ Assert.AreEqual("Index", result.ViewName);
+ Assert.IsNotNull(result, "View Result is null");
+ Assert.IsInstanceOf(typeof(IEnumerable),
+ result.ViewData.Model, "Wrong View Model");
+ var expenses = result.ViewData.Model as IEnumerable;
+ Assert.AreEqual(3, expenses.Count(), "Got wrong number of Categories");
+ }
+ private IEnumerable GetMockExpenses()
+ {
+ IEnumerable fakeExpenses = new List {
+ new Expense { Transaction="expense1", Date=DateTime.Now, Amount=1500 },
+ new Expense { Transaction="expense2", Date=DateTime.Now, Amount=2500 },
+ new Expense { Transaction="expense3", Date=DateTime.Now, Amount=3500 }
+ }.AsEnumerable();
+ return fakeExpenses;
+ }
+ [Test]
+ public void Cannot_Create_Empty_Expense()
+ {
+ // Arrange
+ ExpenseController controller = new ExpenseController(commandBus.Object, categoryRepository.Object, expenseRepository.Object);
+ // The MVC pipeline doesn't run, so binding and validation don't run.
+ controller.ModelState.AddModelError("", "mock error message");
+ Mapper.CreateMap();
+ // Act
+ ExpenseFormModel expense = new ExpenseFormModel();
+ expense.ExpenseId = 0;
+ var result = controller.Save(expense) as ViewResult;
+ // Assert - check that we are passing an invalid model to the view
+ Assert.AreEqual(false, result.ViewData.ModelState.IsValid);
+ Assert.AreEqual("Create", result.ViewName);
+ }
+ [Test]
+ public void Create_Expense_Redirects_To_Index()
+ {
+ // Arrange
+ ExpenseController controller = new ExpenseController(commandBus.Object, categoryRepository.Object, expenseRepository.Object);
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ Mapper.CreateMap();
+ // Act
+ ExpenseFormModel expense = new ExpenseFormModel
+ {
+ Transaction = "Mock Transaction",
+ Date = DateTime.Now,
+ Amount = 1000,
+ CategoryId = 1
+ };
+ var result = controller.Save(expense) as RedirectToRouteResult;
+ // Assert
+ Assert.AreEqual("Index", result.RouteValues["action"]);
+ }
+ [Test]
+ public void Delete_Expense_ReturnsPartial()
+ {
+ // Arrange
+ ExpenseController controller = new ExpenseController(commandBus.Object, categoryRepository.Object, expenseRepository.Object);
+ commandBus.Setup(c => c.Submit(It.IsAny())).Returns(new CommandResult(true));
+ IEnumerable fakeExpenses = GetMockExpenses();
+ expenseRepository.Setup(x => x.GetMany(It.IsAny>>())).Returns(fakeExpenses);
+ // Act
+ var result = controller.Delete(1) as PartialViewResult;
+ // Assert
+ Assert.IsInstanceOf(typeof(IEnumerable),
+ result.ViewData.Model, "Wrong View Model");
+ Assert.AreEqual("_ExpenseList", result.ViewName);
+ }
+ }
+}
diff --git a/EFMVC.Tests/Controllers/HomeControllerTest.cs b/EFMVC.Tests/Controllers/HomeControllerTest.cs
new file mode 100644
index 0000000..074c3cb
--- /dev/null
+++ b/EFMVC.Tests/Controllers/HomeControllerTest.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web.Mvc;
+using NUnit.Framework;
+using EFMVC.Web.Controllers;
+namespace EFMVC.Tests.Controllers
+{
+ [TestFixture]
+ public class HomeControllerTest
+ {
+ [Test]
+ public void Index()
+ {
+ // Arrange
+ HomeController controller = new HomeController();
+ // Act
+ ViewResult result = controller.Index() as ViewResult;
+ // Assert
+ ViewDataDictionary viewData = result.ViewData;
+ Assert.AreEqual("Welcome to EFMVC!", viewData["Message"]);
+ }
+
+ [Test]
+ public void About()
+ {
+ // Arrange
+ HomeController controller = new HomeController();
+ // Act
+ ViewResult result = controller.About() as ViewResult;
+ // Assert
+ Assert.IsNotNull(result);
+ }
+ }
+}
diff --git a/EFMVC.Tests/EFMVC.Tests.csproj b/EFMVC.Tests/EFMVC.Tests.csproj
new file mode 100644
index 0000000..275cf8a
--- /dev/null
+++ b/EFMVC.Tests/EFMVC.Tests.csproj
@@ -0,0 +1,118 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {4A9546B5-60F4-4442-AD76-5486FB91D6CC}
+ Library
+ Properties
+ EFMVC.Tests
+ EFMVC.Tests
+ v4.5
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+ False
+ ..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll
+
+
+ ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll
+
+
+ False
+ ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\NUnit.2.6.2\lib\nunit.framework.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {955fd94a-bbc1-4469-889a-740fb98338de}
+ EFMVC.CommandProcessor
+
+
+ {c73d0df7-d21b-4e15-a8aa-70540236d452}
+ EFMVC.Core
+
+
+ {6a4c3b88-230d-4c19-945e-4685876aa31d}
+ EFMVC.Data
+
+
+ {5aa95e73-cbdd-460e-96f9-4a3da709dfe0}
+ EFMVC.Domain
+
+
+ {0cb7b2db-aeca-421a-aa9f-bff8b532d535}
+ EFMVC.Model
+
+
+ {8739f83b-a769-4fb8-a5b5-d96d640db716}
+ EFMVC.Web.API
+
+
+ {dbf57927-89db-4526-a8e0-5c5ac90096b1}
+ EFMVC.Web.Core
+
+
+ {169afe38-1ca2-4624-bdc4-78c6653b04bd}
+ EFMVC.Web
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Tests/Properties/AssemblyInfo.cs b/EFMVC.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fbe9d75
--- /dev/null
+++ b/EFMVC.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("EFMVC.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("EFMVC.Tests")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("541ecd67-19d1-4b5e-aa08-bccecdb766c5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/EFMVC.Tests/packages.config b/EFMVC.Tests/packages.config
new file mode 100644
index 0000000..0e615b7
--- /dev/null
+++ b/EFMVC.Tests/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/App_Start/BundleConfig.cs b/EFMVC.Web.API/App_Start/BundleConfig.cs
new file mode 100644
index 0000000..eef5466
--- /dev/null
+++ b/EFMVC.Web.API/App_Start/BundleConfig.cs
@@ -0,0 +1,43 @@
+using System.Web;
+using System.Web.Optimization;
+
+namespace EFMVC.Web.API
+{
+ public class BundleConfig
+ {
+ // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
+ public static void RegisterBundles(BundleCollection bundles)
+ {
+ bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
+ "~/Scripts/jquery-{version}.js"));
+
+ bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
+ "~/Scripts/jquery-ui-{version}.js"));
+
+ bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
+ "~/Scripts/jquery.unobtrusive*",
+ "~/Scripts/jquery.validate*"));
+
+ // Use the development version of Modernizr to develop with and learn from. Then, when you're
+ // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
+ bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
+ "~/Scripts/modernizr-*"));
+
+ bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
+
+ bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
+ "~/Content/themes/base/jquery.ui.core.css",
+ "~/Content/themes/base/jquery.ui.resizable.css",
+ "~/Content/themes/base/jquery.ui.selectable.css",
+ "~/Content/themes/base/jquery.ui.accordion.css",
+ "~/Content/themes/base/jquery.ui.autocomplete.css",
+ "~/Content/themes/base/jquery.ui.button.css",
+ "~/Content/themes/base/jquery.ui.dialog.css",
+ "~/Content/themes/base/jquery.ui.slider.css",
+ "~/Content/themes/base/jquery.ui.tabs.css",
+ "~/Content/themes/base/jquery.ui.datepicker.css",
+ "~/Content/themes/base/jquery.ui.progressbar.css",
+ "~/Content/themes/base/jquery.ui.theme.css"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/App_Start/FilterConfig.cs b/EFMVC.Web.API/App_Start/FilterConfig.cs
new file mode 100644
index 0000000..89dfff2
--- /dev/null
+++ b/EFMVC.Web.API/App_Start/FilterConfig.cs
@@ -0,0 +1,13 @@
+using System.Web;
+using System.Web.Mvc;
+
+namespace EFMVC.Web.API
+{
+ public class FilterConfig
+ {
+ public static void RegisterGlobalFilters(GlobalFilterCollection filters)
+ {
+ filters.Add(new HandleErrorAttribute());
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/App_Start/RouteConfig.cs b/EFMVC.Web.API/App_Start/RouteConfig.cs
new file mode 100644
index 0000000..9510e01
--- /dev/null
+++ b/EFMVC.Web.API/App_Start/RouteConfig.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace EFMVC.Web.API
+{
+ public class RouteConfig
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+
+ routes.MapRoute(
+ name: "Default",
+ url: "{controller}/{action}/{id}",
+ defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/App_Start/WebApiConfig.cs b/EFMVC.Web.API/App_Start/WebApiConfig.cs
new file mode 100644
index 0000000..75b0d36
--- /dev/null
+++ b/EFMVC.Web.API/App_Start/WebApiConfig.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Http;
+
+namespace EFMVC.Web.API
+{
+ public static class WebApiConfig
+ {
+ public static void Register(HttpConfiguration config)
+ {
+ config.Routes.MapHttpRoute(
+ name: "DefaultApi",
+ routeTemplate: "api/{controller}/{id}",
+ defaults: new { id = RouteParameter.Optional }
+ );
+
+ // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable return type.
+ // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
+ // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
+ //config.EnableQuerySupport();
+
+ // To disable tracing in your application, please comment out or remove the following line of code
+ // For more information, refer to: http://www.asp.net/web-api
+ config.EnableSystemDiagnosticsTracing();
+ }
+ }
+}
diff --git a/EFMVC.Web.API/Areas/HelpPage/ApiDescriptionExtensions.cs b/EFMVC.Web.API/Areas/HelpPage/ApiDescriptionExtensions.cs
new file mode 100644
index 0000000..0be8f3a
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/ApiDescriptionExtensions.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Text;
+using System.Web;
+using System.Web.Http.Description;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ public static class ApiDescriptionExtensions
+ {
+ ///
+ /// Generates an URI-friendly ID for the . E.g. "Get-Values-id_name" instead of "GetValues/{id}?name={name}"
+ ///
+ /// The .
+ /// The ID as a string.
+ public static string GetFriendlyId(this ApiDescription description)
+ {
+ string path = description.RelativePath;
+ string[] urlParts = path.Split('?');
+ string localPath = urlParts[0];
+ string queryKeyString = null;
+ if (urlParts.Length > 1)
+ {
+ string query = urlParts[1];
+ string[] queryKeys = HttpUtility.ParseQueryString(query).AllKeys;
+ queryKeyString = String.Join("_", queryKeys);
+ }
+
+ StringBuilder friendlyPath = new StringBuilder();
+ friendlyPath.AppendFormat("{0}-{1}",
+ description.HttpMethod.Method,
+ localPath.Replace("/", "-").Replace("{", String.Empty).Replace("}", String.Empty));
+ if (queryKeyString != null)
+ {
+ friendlyPath.AppendFormat("_{0}", queryKeyString);
+ }
+ return friendlyPath.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/App_Start/HelpPageConfig.cs b/EFMVC.Web.API/Areas/HelpPage/App_Start/HelpPageConfig.cs
new file mode 100644
index 0000000..eff343b
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/App_Start/HelpPageConfig.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http.Headers;
+using System.Web;
+using System.Web.Http;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// Use this class to customize the Help Page.
+ /// For example you can set a custom to supply the documentation
+ /// or you can provide the samples for the requests/responses.
+ ///
+ public static class HelpPageConfig
+ {
+ public static void Register(HttpConfiguration config)
+ {
+ //// Uncomment the following to use the documentation from XML documentation file.
+ //config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
+
+ //// Uncomment the following to use "sample string" as the sample for all actions that have string as the body parameter or return type.
+ //// Also, the string arrays will be used for IEnumerable. The sample objects will be serialized into different media type
+ //// formats by the available formatters.
+ //config.SetSampleObjects(new Dictionary
+ //{
+ // {typeof(string), "sample string"},
+ // {typeof(IEnumerable), new string[]{"sample 1", "sample 2"}}
+ //});
+
+ //// Uncomment the following to use "[0]=foo&[1]=bar" directly as the sample for all actions that support form URL encoded format
+ //// and have IEnumerable as the body parameter or return type.
+ //config.SetSampleForType("[0]=foo&[1]=bar", new MediaTypeHeaderValue("application/x-www-form-urlencoded"), typeof(IEnumerable));
+
+ //// Uncomment the following to use "1234" directly as the request sample for media type "text/plain" on the controller named "Values"
+ //// and action named "Put".
+ //config.SetSampleRequest("1234", new MediaTypeHeaderValue("text/plain"), "Values", "Put");
+
+ //// Uncomment the following to use the image on "../images/aspNetHome.png" directly as the response sample for media type "image/png"
+ //// on the controller named "Values" and action named "Get" with parameter "id".
+ //config.SetSampleResponse(new ImageSample("../images/aspNetHome.png"), new MediaTypeHeaderValue("image/png"), "Values", "Get", "id");
+
+ //// Uncomment the following to correct the sample request when the action expects an HttpRequestMessage with ObjectContent.
+ //// The sample will be generated as if the controller named "Values" and action named "Get" were having string as the body parameter.
+ //config.SetActualRequestType(typeof(string), "Values", "Get");
+
+ //// Uncomment the following to correct the sample response when the action returns an HttpResponseMessage with ObjectContent.
+ //// The sample will be generated as if the controller named "Values" and action named "Post" were returning a string.
+ //config.SetActualResponseType(typeof(string), "Values", "Post");
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Controllers/HelpController.cs b/EFMVC.Web.API/Areas/HelpPage/Controllers/HelpController.cs
new file mode 100644
index 0000000..57aa0ca
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Controllers/HelpController.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Web.Http;
+using System.Web.Mvc;
+using EFMVC.Web.API.Areas.HelpPage.Models;
+
+namespace EFMVC.Web.API.Areas.HelpPage.Controllers
+{
+ ///
+ /// The controller that will handle requests for the help page.
+ ///
+ public class HelpController : Controller
+ {
+ public HelpController()
+ : this(GlobalConfiguration.Configuration)
+ {
+ }
+
+ public HelpController(HttpConfiguration config)
+ {
+ Configuration = config;
+ }
+
+ public HttpConfiguration Configuration { get; private set; }
+
+ public ActionResult Index()
+ {
+ return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
+ }
+
+ public ActionResult Api(string apiId)
+ {
+ if (!String.IsNullOrEmpty(apiId))
+ {
+ HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
+ if (apiModel != null)
+ {
+ return View(apiModel);
+ }
+ }
+
+ return View("Error");
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/HelpPage.css b/EFMVC.Web.API/Areas/HelpPage/HelpPage.css
new file mode 100644
index 0000000..ee461e0
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/HelpPage.css
@@ -0,0 +1,89 @@
+pre.wrapped {
+ white-space: -moz-pre-wrap;
+ white-space: -pre-wrap;
+ white-space: -o-pre-wrap;
+ white-space: pre-wrap;
+}
+
+.warning-message-container {
+ margin-top: 20px;
+ padding: 0 10px;
+ color: #525252;
+ background: #EFDCA9;
+ border: 1px solid #CCCCCC;
+}
+
+.help-page-table {
+ width: 100%;
+ border-collapse: collapse;
+ text-align: left;
+ margin: 0px 0px 20px 0px;
+ border-top: 2px solid #D4D4D4;
+}
+
+.help-page-table th {
+ text-align: left;
+ font-weight: bold;
+ border-bottom: 2px solid #D4D4D4;
+ padding: 8px 6px 8px 6px;
+}
+
+.help-page-table td {
+ border-bottom: 2px solid #D4D4D4;
+ padding: 15px 8px 15px 8px;
+ vertical-align: top;
+}
+
+.help-page-table pre, .help-page-table p {
+ margin: 0px;
+ padding: 0px;
+ font-family: inherit;
+ font-size: 100%;
+}
+
+.help-page-table tbody tr:hover td {
+ background-color: #F3F3F3;
+}
+
+a:hover {
+ background-color: transparent;
+}
+
+.sample-header {
+ border: 2px solid #D4D4D4;
+ background: #76B8DB;
+ color: #FFFFFF;
+ padding: 8px 15px;
+ border-bottom: none;
+ display: inline-block;
+ margin: 10px 0px 0px 0px;
+}
+
+.sample-content {
+ display: block;
+ border-width: 0;
+ padding: 15px 20px;
+ background: #FFFFFF;
+ border: 2px solid #D4D4D4;
+ margin: 0px 0px 10px 0px;
+}
+
+.api-name {
+ width: 40%;
+}
+
+.api-documentation {
+ width: 60%;
+}
+
+.parameter-name {
+ width: 20%;
+}
+
+.parameter-documentation {
+ width: 50%;
+}
+
+.parameter-source {
+ width: 30%;
+}
diff --git a/EFMVC.Web.API/Areas/HelpPage/HelpPageAreaRegistration.cs b/EFMVC.Web.API/Areas/HelpPage/HelpPageAreaRegistration.cs
new file mode 100644
index 0000000..588466a
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/HelpPageAreaRegistration.cs
@@ -0,0 +1,26 @@
+using System.Web.Http;
+using System.Web.Mvc;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ public class HelpPageAreaRegistration : AreaRegistration
+ {
+ public override string AreaName
+ {
+ get
+ {
+ return "HelpPage";
+ }
+ }
+
+ public override void RegisterArea(AreaRegistrationContext context)
+ {
+ context.MapRoute(
+ "HelpPage_Default",
+ "Help/{action}/{apiId}",
+ new { controller = "Help", action = "Index", apiId = UrlParameter.Optional });
+
+ HelpPageConfig.Register(GlobalConfiguration.Configuration);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/HelpPageConfigurationExtensions.cs b/EFMVC.Web.API/Areas/HelpPage/HelpPageConfigurationExtensions.cs
new file mode 100644
index 0000000..e850fda
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/HelpPageConfigurationExtensions.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Web.Http;
+using System.Web.Http.Description;
+using EFMVC.Web.API.Areas.HelpPage.Models;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ public static class HelpPageConfigurationExtensions
+ {
+ private const string ApiModelPrefix = "MS_HelpPageApiModel_";
+
+ ///
+ /// Sets the documentation provider for help page.
+ ///
+ /// The .
+ /// The documentation provider.
+ public static void SetDocumentationProvider(this HttpConfiguration config, IDocumentationProvider documentationProvider)
+ {
+ config.Services.Replace(typeof(IDocumentationProvider), documentationProvider);
+ }
+
+ ///
+ /// Sets the objects that will be used by the formatters to produce sample requests/responses.
+ ///
+ /// The .
+ /// The sample objects.
+ public static void SetSampleObjects(this HttpConfiguration config, IDictionary sampleObjects)
+ {
+ config.GetHelpPageSampleGenerator().SampleObjects = sampleObjects;
+ }
+
+ ///
+ /// Sets the sample request directly for the specified media type and action.
+ ///
+ /// The .
+ /// The sample request.
+ /// The media type.
+ /// Name of the controller.
+ /// Name of the action.
+ public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
+ {
+ config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, new[] { "*" }), sample);
+ }
+
+ ///
+ /// Sets the sample request directly for the specified media type and action with parameters.
+ ///
+ /// The .
+ /// The sample request.
+ /// The media type.
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
+ {
+ config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, parameterNames), sample);
+ }
+
+ ///
+ /// Sets the sample request directly for the specified media type of the action.
+ ///
+ /// The .
+ /// The sample response.
+ /// The media type.
+ /// Name of the controller.
+ /// Name of the action.
+ public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
+ {
+ config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, new[] { "*" }), sample);
+ }
+
+ ///
+ /// Sets the sample response directly for the specified media type of the action with specific parameters.
+ ///
+ /// The .
+ /// The sample response.
+ /// The media type.
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
+ {
+ config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, parameterNames), sample);
+ }
+
+ ///
+ /// Sets the sample directly for all actions with the specified type and media type.
+ ///
+ /// The .
+ /// The sample.
+ /// The media type.
+ /// The parameter type or return type of an action.
+ public static void SetSampleForType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, Type type)
+ {
+ config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, type), sample);
+ }
+
+ ///
+ /// Specifies the actual type of passed to the in an action.
+ /// The help page will use this information to produce more accurate request samples.
+ ///
+ /// The .
+ /// The type.
+ /// Name of the controller.
+ /// Name of the action.
+ public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName)
+ {
+ config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, new[] { "*" }), type);
+ }
+
+ ///
+ /// Specifies the actual type of passed to the in an action.
+ /// The help page will use this information to produce more accurate request samples.
+ ///
+ /// The .
+ /// The type.
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
+ {
+ config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, parameterNames), type);
+ }
+
+ ///
+ /// Specifies the actual type of returned as part of the in an action.
+ /// The help page will use this information to produce more accurate response samples.
+ ///
+ /// The .
+ /// The type.
+ /// Name of the controller.
+ /// Name of the action.
+ public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName)
+ {
+ config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, new[] { "*" }), type);
+ }
+
+ ///
+ /// Specifies the actual type of returned as part of the in an action.
+ /// The help page will use this information to produce more accurate response samples.
+ ///
+ /// The .
+ /// The type.
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
+ {
+ config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, parameterNames), type);
+ }
+
+ ///
+ /// Gets the help page sample generator.
+ ///
+ /// The .
+ /// The help page sample generator.
+ public static HelpPageSampleGenerator GetHelpPageSampleGenerator(this HttpConfiguration config)
+ {
+ return (HelpPageSampleGenerator)config.Properties.GetOrAdd(
+ typeof(HelpPageSampleGenerator),
+ k => new HelpPageSampleGenerator());
+ }
+
+ ///
+ /// Sets the help page sample generator.
+ ///
+ /// The .
+ /// The help page sample generator.
+ public static void SetHelpPageSampleGenerator(this HttpConfiguration config, HelpPageSampleGenerator sampleGenerator)
+ {
+ config.Properties.AddOrUpdate(
+ typeof(HelpPageSampleGenerator),
+ k => sampleGenerator,
+ (k, o) => sampleGenerator);
+ }
+
+ ///
+ /// Gets the model that represents an API displayed on the help page. The model is initialized on the first call and cached for subsequent calls.
+ ///
+ /// The .
+ /// The ID.
+ ///
+ /// An
+ ///
+ public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
+ {
+ object model;
+ string modelId = ApiModelPrefix + apiDescriptionId;
+ if (!config.Properties.TryGetValue(modelId, out model))
+ {
+ Collection apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
+ ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
+ if (apiDescription != null)
+ {
+ HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
+ model = GenerateApiModel(apiDescription, sampleGenerator);
+ config.Properties.TryAdd(modelId, model);
+ }
+ }
+
+ return (HelpPageApiModel)model;
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as ErrorMessages.")]
+ private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HelpPageSampleGenerator sampleGenerator)
+ {
+ HelpPageApiModel apiModel = new HelpPageApiModel();
+ apiModel.ApiDescription = apiDescription;
+
+ try
+ {
+ foreach (var item in sampleGenerator.GetSampleRequests(apiDescription))
+ {
+ apiModel.SampleRequests.Add(item.Key, item.Value);
+ LogInvalidSampleAsError(apiModel, item.Value);
+ }
+
+ foreach (var item in sampleGenerator.GetSampleResponses(apiDescription))
+ {
+ apiModel.SampleResponses.Add(item.Key, item.Value);
+ LogInvalidSampleAsError(apiModel, item.Value);
+ }
+ }
+ catch (Exception e)
+ {
+ apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture, "An exception has occurred while generating the sample. Exception Message: {0}", e.Message));
+ }
+
+ return apiModel;
+ }
+
+ private static void LogInvalidSampleAsError(HelpPageApiModel apiModel, object sample)
+ {
+ InvalidSample invalidSample = sample as InvalidSample;
+ if (invalidSample != null)
+ {
+ apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);
+ }
+ }
+ }
+}
diff --git a/EFMVC.Web.API/Areas/HelpPage/Models/HelpPageApiModel.cs b/EFMVC.Web.API/Areas/HelpPage/Models/HelpPageApiModel.cs
new file mode 100644
index 0000000..d5f3f38
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Models/HelpPageApiModel.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Net.Http.Headers;
+using System.Web.Http.Description;
+
+namespace EFMVC.Web.API.Areas.HelpPage.Models
+{
+ ///
+ /// The model that represents an API displayed on the help page.
+ ///
+ public class HelpPageApiModel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public HelpPageApiModel()
+ {
+ SampleRequests = new Dictionary();
+ SampleResponses = new Dictionary();
+ ErrorMessages = new Collection();
+ }
+
+ ///
+ /// Gets or sets the that describes the API.
+ ///
+ public ApiDescription ApiDescription { get; set; }
+
+ ///
+ /// Gets the sample requests associated with the API.
+ ///
+ public IDictionary SampleRequests { get; private set; }
+
+ ///
+ /// Gets the sample responses associated with the API.
+ ///
+ public IDictionary SampleResponses { get; private set; }
+
+ ///
+ /// Gets the error messages associated with this model.
+ ///
+ public Collection ErrorMessages { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleGenerator.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleGenerator.cs
new file mode 100644
index 0000000..ff4fad6
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleGenerator.cs
@@ -0,0 +1,372 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Formatting;
+using System.Net.Http.Headers;
+using System.Web.Http.Description;
+using System.Xml.Linq;
+using Newtonsoft.Json;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This class will generate the samples for the help page.
+ ///
+ public class HelpPageSampleGenerator
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public HelpPageSampleGenerator()
+ {
+ ActualHttpMessageTypes = new Dictionary();
+ ActionSamples = new Dictionary();
+ SampleObjects = new Dictionary();
+ }
+
+ ///
+ /// Gets CLR types that are used as the content of or .
+ ///
+ public IDictionary ActualHttpMessageTypes { get; internal set; }
+
+ ///
+ /// Gets the objects that are used directly as samples for certain actions.
+ ///
+ public IDictionary ActionSamples { get; internal set; }
+
+ ///
+ /// Gets the objects that are serialized as samples by the supported formatters.
+ ///
+ public IDictionary SampleObjects { get; internal set; }
+
+ ///
+ /// Gets the request body samples for a given .
+ ///
+ /// The .
+ /// The samples keyed by media type.
+ public IDictionary GetSampleRequests(ApiDescription api)
+ {
+ return GetSample(api, SampleDirection.Request);
+ }
+
+ ///
+ /// Gets the response body samples for a given .
+ ///
+ /// The .
+ /// The samples keyed by media type.
+ public IDictionary GetSampleResponses(ApiDescription api)
+ {
+ return GetSample(api, SampleDirection.Response);
+ }
+
+ ///
+ /// Gets the request or response body samples.
+ ///
+ /// The .
+ /// The value indicating whether the sample is for a request or for a response.
+ /// The samples keyed by media type.
+ public virtual IDictionary GetSample(ApiDescription api, SampleDirection sampleDirection)
+ {
+ if (api == null)
+ {
+ throw new ArgumentNullException("api");
+ }
+ string controllerName = api.ActionDescriptor.ControllerDescriptor.ControllerName;
+ string actionName = api.ActionDescriptor.ActionName;
+ IEnumerable parameterNames = api.ParameterDescriptions.Select(p => p.Name);
+ Collection formatters;
+ Type type = ResolveType(api, controllerName, actionName, parameterNames, sampleDirection, out formatters);
+ var samples = new Dictionary();
+
+ // Use the samples provided directly for actions
+ var actionSamples = GetAllActionSamples(controllerName, actionName, parameterNames, sampleDirection);
+ foreach (var actionSample in actionSamples)
+ {
+ samples.Add(actionSample.Key.MediaType, WrapSampleIfString(actionSample.Value));
+ }
+
+ // Do the sample generation based on formatters only if an action doesn't return an HttpResponseMessage.
+ // Here we cannot rely on formatters because we don't know what's in the HttpResponseMessage, it might not even use formatters.
+ if (type != null && !typeof(HttpResponseMessage).IsAssignableFrom(type))
+ {
+ object sampleObject = GetSampleObject(type);
+ foreach (var formatter in formatters)
+ {
+ foreach (MediaTypeHeaderValue mediaType in formatter.SupportedMediaTypes)
+ {
+ if (!samples.ContainsKey(mediaType))
+ {
+ object sample = GetActionSample(controllerName, actionName, parameterNames, type, formatter, mediaType, sampleDirection);
+
+ // If no sample found, try generate sample using formatter and sample object
+ if (sample == null && sampleObject != null)
+ {
+ sample = WriteSampleObjectUsingFormatter(formatter, sampleObject, type, mediaType);
+ }
+
+ samples.Add(mediaType, WrapSampleIfString(sample));
+ }
+ }
+ }
+ }
+
+ return samples;
+ }
+
+ ///
+ /// Search for samples that are provided directly through .
+ ///
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ /// The CLR type.
+ /// The formatter.
+ /// The media type.
+ /// The value indicating whether the sample is for a request or for a response.
+ /// The sample that matches the parameters.
+ public virtual object GetActionSample(string controllerName, string actionName, IEnumerable parameterNames, Type type, MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType, SampleDirection sampleDirection)
+ {
+ object sample;
+
+ // First, try get sample provided for a specific mediaType, controllerName, actionName and parameterNames.
+ // If not found, try get the sample provided for a specific mediaType, controllerName and actionName regardless of the parameterNames
+ // If still not found, try get the sample provided for a specific type and mediaType
+ if (ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, sampleDirection, controllerName, actionName, parameterNames), out sample) ||
+ ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, sampleDirection, controllerName, actionName, new[] { "*" }), out sample) ||
+ ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, type), out sample))
+ {
+ return sample;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets the sample object that will be serialized by the formatters.
+ /// First, it will look at the . If no sample object is found, it will try to create one using .
+ ///
+ /// The type.
+ /// The sample object.
+ public virtual object GetSampleObject(Type type)
+ {
+ object sampleObject;
+
+ if (!SampleObjects.TryGetValue(type, out sampleObject))
+ {
+ // Try create a default sample object
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ sampleObject = objectGenerator.GenerateObject(type);
+ }
+
+ return sampleObject;
+ }
+
+ ///
+ /// Resolves the type of the action parameter or return value when or is used.
+ ///
+ /// The .
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ /// The value indicating whether the sample is for a request or a response.
+ /// The formatters.
+ [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", Justification = "This is only used in advanced scenarios.")]
+ public virtual Type ResolveType(ApiDescription api, string controllerName, string actionName, IEnumerable parameterNames, SampleDirection sampleDirection, out Collection formatters)
+ {
+ if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
+ {
+ throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
+ }
+ if (api == null)
+ {
+ throw new ArgumentNullException("api");
+ }
+ Type type;
+ if (ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, parameterNames), out type) ||
+ ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, new[] { "*" }), out type))
+ {
+ // Re-compute the supported formatters based on type
+ Collection newFormatters = new Collection();
+ foreach (var formatter in api.ActionDescriptor.Configuration.Formatters)
+ {
+ if (IsFormatSupported(sampleDirection, formatter, type))
+ {
+ newFormatters.Add(formatter);
+ }
+ }
+ formatters = newFormatters;
+ }
+ else
+ {
+ switch (sampleDirection)
+ {
+ case SampleDirection.Request:
+ ApiParameterDescription requestBodyParameter = api.ParameterDescriptions.FirstOrDefault(p => p.Source == ApiParameterSource.FromBody);
+ type = requestBodyParameter == null ? null : requestBodyParameter.ParameterDescriptor.ParameterType;
+ formatters = api.SupportedRequestBodyFormatters;
+ break;
+ case SampleDirection.Response:
+ default:
+ type = api.ActionDescriptor.ReturnType;
+ formatters = api.SupportedResponseFormatters;
+ break;
+ }
+ }
+
+ return type;
+ }
+
+ ///
+ /// Writes the sample object using formatter.
+ ///
+ /// The formatter.
+ /// The value.
+ /// The type.
+ /// Type of the media.
+ ///
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as InvalidSample.")]
+ public virtual object WriteSampleObjectUsingFormatter(MediaTypeFormatter formatter, object value, Type type, MediaTypeHeaderValue mediaType)
+ {
+ if (formatter == null)
+ {
+ throw new ArgumentNullException("formatter");
+ }
+ if (mediaType == null)
+ {
+ throw new ArgumentNullException("mediaType");
+ }
+
+ object sample = String.Empty;
+ MemoryStream ms = null;
+ HttpContent content = null;
+ try
+ {
+ if (formatter.CanWriteType(type))
+ {
+ ms = new MemoryStream();
+ content = new ObjectContent(type, value, formatter, mediaType);
+ formatter.WriteToStreamAsync(type, value, ms, content, null).Wait();
+ ms.Position = 0;
+ StreamReader reader = new StreamReader(ms);
+ string serializedSampleString = reader.ReadToEnd();
+ if (mediaType.MediaType.ToUpperInvariant().Contains("XML"))
+ {
+ serializedSampleString = TryFormatXml(serializedSampleString);
+ }
+ else if (mediaType.MediaType.ToUpperInvariant().Contains("JSON"))
+ {
+ serializedSampleString = TryFormatJson(serializedSampleString);
+ }
+
+ sample = new TextSample(serializedSampleString);
+ }
+ else
+ {
+ sample = new InvalidSample(String.Format(
+ CultureInfo.CurrentCulture,
+ "Failed to generate the sample for media type '{0}'. Cannot use formatter '{1}' to write type '{2}'.",
+ mediaType,
+ formatter.GetType().Name,
+ type.Name));
+ }
+ }
+ catch (Exception e)
+ {
+ sample = new InvalidSample(String.Format(
+ CultureInfo.CurrentCulture,
+ "An exception has occurred while using the formatter '{0}' to generate sample for media type '{1}'. Exception message: {2}",
+ formatter.GetType().Name,
+ mediaType.MediaType,
+ e.Message));
+ }
+ finally
+ {
+ if (ms != null)
+ {
+ ms.Dispose();
+ }
+ if (content != null)
+ {
+ content.Dispose();
+ }
+ }
+
+ return sample;
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
+ private static string TryFormatJson(string str)
+ {
+ try
+ {
+ object parsedJson = JsonConvert.DeserializeObject(str);
+ return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
+ }
+ catch
+ {
+ // can't parse JSON, return the original string
+ return str;
+ }
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
+ private static string TryFormatXml(string str)
+ {
+ try
+ {
+ XDocument xml = XDocument.Parse(str);
+ return xml.ToString();
+ }
+ catch
+ {
+ // can't parse XML, return the original string
+ return str;
+ }
+ }
+
+ private static bool IsFormatSupported(SampleDirection sampleDirection, MediaTypeFormatter formatter, Type type)
+ {
+ switch (sampleDirection)
+ {
+ case SampleDirection.Request:
+ return formatter.CanReadType(type);
+ case SampleDirection.Response:
+ return formatter.CanWriteType(type);
+ }
+ return false;
+ }
+
+ private IEnumerable> GetAllActionSamples(string controllerName, string actionName, IEnumerable parameterNames, SampleDirection sampleDirection)
+ {
+ HashSet parameterNamesSet = new HashSet(parameterNames, StringComparer.OrdinalIgnoreCase);
+ foreach (var sample in ActionSamples)
+ {
+ HelpPageSampleKey sampleKey = sample.Key;
+ if (String.Equals(controllerName, sampleKey.ControllerName, StringComparison.OrdinalIgnoreCase) &&
+ String.Equals(actionName, sampleKey.ActionName, StringComparison.OrdinalIgnoreCase) &&
+ (sampleKey.ParameterNames.SetEquals(new[] { "*" }) || parameterNamesSet.SetEquals(sampleKey.ParameterNames)) &&
+ sampleDirection == sampleKey.SampleDirection)
+ {
+ yield return sample;
+ }
+ }
+ }
+
+ private static object WrapSampleIfString(object sample)
+ {
+ string stringSample = sample as string;
+ if (stringSample != null)
+ {
+ return new TextSample(stringSample);
+ }
+
+ return sample;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleKey.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleKey.cs
new file mode 100644
index 0000000..3c1ff88
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/HelpPageSampleKey.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Net.Http.Headers;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This is used to identify the place where the sample should be applied.
+ ///
+ public class HelpPageSampleKey
+ {
+ ///
+ /// Creates a new based on media type and CLR type.
+ ///
+ /// The media type.
+ /// The CLR type.
+ public HelpPageSampleKey(MediaTypeHeaderValue mediaType, Type type)
+ {
+ if (mediaType == null)
+ {
+ throw new ArgumentNullException("mediaType");
+ }
+ if (type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ ControllerName = String.Empty;
+ ActionName = String.Empty;
+ ParameterNames = new HashSet(StringComparer.OrdinalIgnoreCase);
+ ParameterType = type;
+ MediaType = mediaType;
+ }
+
+ ///
+ /// Creates a new based on , controller name, action name and parameter names.
+ ///
+ /// The .
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public HelpPageSampleKey(SampleDirection sampleDirection, string controllerName, string actionName, IEnumerable parameterNames)
+ {
+ if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
+ {
+ throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
+ }
+ if (controllerName == null)
+ {
+ throw new ArgumentNullException("controllerName");
+ }
+ if (actionName == null)
+ {
+ throw new ArgumentNullException("actionName");
+ }
+ if (parameterNames == null)
+ {
+ throw new ArgumentNullException("parameterNames");
+ }
+ ControllerName = controllerName;
+ ActionName = actionName;
+ ParameterNames = new HashSet(parameterNames, StringComparer.OrdinalIgnoreCase);
+ SampleDirection = sampleDirection;
+ }
+
+ ///
+ /// Creates a new based on media type, , controller name, action name and parameter names.
+ ///
+ /// The media type.
+ /// The .
+ /// Name of the controller.
+ /// Name of the action.
+ /// The parameter names.
+ public HelpPageSampleKey(MediaTypeHeaderValue mediaType, SampleDirection sampleDirection, string controllerName, string actionName, IEnumerable parameterNames)
+ {
+ if (mediaType == null)
+ {
+ throw new ArgumentNullException("mediaType");
+ }
+ if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
+ {
+ throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
+ }
+ if (controllerName == null)
+ {
+ throw new ArgumentNullException("controllerName");
+ }
+ if (actionName == null)
+ {
+ throw new ArgumentNullException("actionName");
+ }
+ if (parameterNames == null)
+ {
+ throw new ArgumentNullException("parameterNames");
+ }
+ ControllerName = controllerName;
+ ActionName = actionName;
+ MediaType = mediaType;
+ ParameterNames = new HashSet(parameterNames, StringComparer.OrdinalIgnoreCase);
+ SampleDirection = sampleDirection;
+ }
+
+ ///
+ /// Gets the name of the controller.
+ ///
+ ///
+ /// The name of the controller.
+ ///
+ public string ControllerName { get; private set; }
+
+ ///
+ /// Gets the name of the action.
+ ///
+ ///
+ /// The name of the action.
+ ///
+ public string ActionName { get; private set; }
+
+ ///
+ /// Gets the media type.
+ ///
+ ///
+ /// The media type.
+ ///
+ public MediaTypeHeaderValue MediaType { get; private set; }
+
+ ///
+ /// Gets the parameter names.
+ ///
+ public HashSet ParameterNames { get; private set; }
+
+ public Type ParameterType { get; private set; }
+
+ ///
+ /// Gets the .
+ ///
+ public SampleDirection? SampleDirection { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ HelpPageSampleKey otherKey = obj as HelpPageSampleKey;
+ if (otherKey == null)
+ {
+ return false;
+ }
+
+ return String.Equals(ControllerName, otherKey.ControllerName, StringComparison.OrdinalIgnoreCase) &&
+ String.Equals(ActionName, otherKey.ActionName, StringComparison.OrdinalIgnoreCase) &&
+ (MediaType == otherKey.MediaType || (MediaType != null && MediaType.Equals(otherKey.MediaType))) &&
+ ParameterType == otherKey.ParameterType &&
+ SampleDirection == otherKey.SampleDirection &&
+ ParameterNames.SetEquals(otherKey.ParameterNames);
+ }
+
+ public override int GetHashCode()
+ {
+ int hashCode = ControllerName.ToUpperInvariant().GetHashCode() ^ ActionName.ToUpperInvariant().GetHashCode();
+ if (MediaType != null)
+ {
+ hashCode ^= MediaType.GetHashCode();
+ }
+ if (SampleDirection != null)
+ {
+ hashCode ^= SampleDirection.GetHashCode();
+ }
+ if (ParameterType != null)
+ {
+ hashCode ^= ParameterType.GetHashCode();
+ }
+ foreach (string parameterName in ParameterNames)
+ {
+ hashCode ^= parameterName.ToUpperInvariant().GetHashCode();
+ }
+
+ return hashCode;
+ }
+ }
+}
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ImageSample.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ImageSample.cs
new file mode 100644
index 0000000..e9e4974
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ImageSample.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This represents an image sample on the help page. There's a display template named ImageSample associated with this class.
+ ///
+ public class ImageSample
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The URL of an image.
+ public ImageSample(string src)
+ {
+ if (src == null)
+ {
+ throw new ArgumentNullException("src");
+ }
+ Src = src;
+ }
+
+ public string Src { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ ImageSample other = obj as ImageSample;
+ return other != null && Src == other.Src;
+ }
+
+ public override int GetHashCode()
+ {
+ return Src.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return Src;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/InvalidSample.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/InvalidSample.cs
new file mode 100644
index 0000000..5f4a0bc
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/InvalidSample.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This represents an invalid sample on the help page. There's a display template named InvalidSample associated with this class.
+ ///
+ public class InvalidSample
+ {
+ public InvalidSample(string errorMessage)
+ {
+ if (errorMessage == null)
+ {
+ throw new ArgumentNullException("errorMessage");
+ }
+ ErrorMessage = errorMessage;
+ }
+
+ public string ErrorMessage { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ InvalidSample other = obj as InvalidSample;
+ return other != null && ErrorMessage == other.ErrorMessage;
+ }
+
+ public override int GetHashCode()
+ {
+ return ErrorMessage.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return ErrorMessage;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ObjectGenerator.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ObjectGenerator.cs
new file mode 100644
index 0000000..b2b0ee1
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/ObjectGenerator.cs
@@ -0,0 +1,456 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This class will create an object of a given type and populate it with sample data.
+ ///
+ public class ObjectGenerator
+ {
+ private const int DefaultCollectionSize = 3;
+ private readonly SimpleTypeObjectGenerator SimpleObjectGenerator = new SimpleTypeObjectGenerator();
+
+ ///
+ /// Generates an object for a given type. The type needs to be public, have a public default constructor and settable public properties/fields. Currently it supports the following types:
+ /// Simple types: , , , , , etc.
+ /// Complex types: POCO types.
+ /// Nullables: .
+ /// Arrays: arrays of simple types or complex types.
+ /// Key value pairs:
+ /// Tuples: , , etc
+ /// Dictionaries: or anything deriving from .
+ /// Collections: , , , , , or anything deriving from or .
+ /// Queryables: , .
+ ///
+ /// The type.
+ /// An object of the given type.
+ public object GenerateObject(Type type)
+ {
+ return GenerateObject(type, new Dictionary());
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Here we just want to return null if anything goes wrong.")]
+ private object GenerateObject(Type type, Dictionary createdObjectReferences)
+ {
+ try
+ {
+ if (SimpleTypeObjectGenerator.CanGenerateObject(type))
+ {
+ return SimpleObjectGenerator.GenerateObject(type);
+ }
+
+ if (type.IsArray)
+ {
+ return GenerateArray(type, DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (type.IsGenericType)
+ {
+ return GenerateGenericType(type, DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (type == typeof(IDictionary))
+ {
+ return GenerateDictionary(typeof(Hashtable), DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (typeof(IDictionary).IsAssignableFrom(type))
+ {
+ return GenerateDictionary(type, DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (type == typeof(IList) ||
+ type == typeof(IEnumerable) ||
+ type == typeof(ICollection))
+ {
+ return GenerateCollection(typeof(ArrayList), DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (typeof(IList).IsAssignableFrom(type))
+ {
+ return GenerateCollection(type, DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (type == typeof(IQueryable))
+ {
+ return GenerateQueryable(type, DefaultCollectionSize, createdObjectReferences);
+ }
+
+ if (type.IsEnum)
+ {
+ return GenerateEnum(type);
+ }
+
+ if (type.IsPublic || type.IsNestedPublic)
+ {
+ return GenerateComplexObject(type, createdObjectReferences);
+ }
+ }
+ catch
+ {
+ // Returns null if anything fails
+ return null;
+ }
+
+ return null;
+ }
+
+ private static object GenerateGenericType(Type type, int collectionSize, Dictionary createdObjectReferences)
+ {
+ Type genericTypeDefinition = type.GetGenericTypeDefinition();
+ if (genericTypeDefinition == typeof(Nullable<>))
+ {
+ return GenerateNullable(type, createdObjectReferences);
+ }
+
+ if (genericTypeDefinition == typeof(KeyValuePair<,>))
+ {
+ return GenerateKeyValuePair(type, createdObjectReferences);
+ }
+
+ if (IsTuple(genericTypeDefinition))
+ {
+ return GenerateTuple(type, createdObjectReferences);
+ }
+
+ Type[] genericArguments = type.GetGenericArguments();
+ if (genericArguments.Length == 1)
+ {
+ if (genericTypeDefinition == typeof(IList<>) ||
+ genericTypeDefinition == typeof(IEnumerable<>) ||
+ genericTypeDefinition == typeof(ICollection<>))
+ {
+ Type collectionType = typeof(List<>).MakeGenericType(genericArguments);
+ return GenerateCollection(collectionType, collectionSize, createdObjectReferences);
+ }
+
+ if (genericTypeDefinition == typeof(IQueryable<>))
+ {
+ return GenerateQueryable(type, collectionSize, createdObjectReferences);
+ }
+
+ Type closedCollectionType = typeof(ICollection<>).MakeGenericType(genericArguments[0]);
+ if (closedCollectionType.IsAssignableFrom(type))
+ {
+ return GenerateCollection(type, collectionSize, createdObjectReferences);
+ }
+ }
+
+ if (genericArguments.Length == 2)
+ {
+ if (genericTypeDefinition == typeof(IDictionary<,>))
+ {
+ Type dictionaryType = typeof(Dictionary<,>).MakeGenericType(genericArguments);
+ return GenerateDictionary(dictionaryType, collectionSize, createdObjectReferences);
+ }
+
+ Type closedDictionaryType = typeof(IDictionary<,>).MakeGenericType(genericArguments[0], genericArguments[1]);
+ if (closedDictionaryType.IsAssignableFrom(type))
+ {
+ return GenerateDictionary(type, collectionSize, createdObjectReferences);
+ }
+ }
+
+ if (type.IsPublic || type.IsNestedPublic)
+ {
+ return GenerateComplexObject(type, createdObjectReferences);
+ }
+
+ return null;
+ }
+
+ private static object GenerateTuple(Type type, Dictionary createdObjectReferences)
+ {
+ Type[] genericArgs = type.GetGenericArguments();
+ object[] parameterValues = new object[genericArgs.Length];
+ bool failedToCreateTuple = true;
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ for (int i = 0; i < genericArgs.Length; i++)
+ {
+ parameterValues[i] = objectGenerator.GenerateObject(genericArgs[i], createdObjectReferences);
+ failedToCreateTuple &= parameterValues[i] == null;
+ }
+ if (failedToCreateTuple)
+ {
+ return null;
+ }
+ object result = Activator.CreateInstance(type, parameterValues);
+ return result;
+ }
+
+ private static bool IsTuple(Type genericTypeDefinition)
+ {
+ return genericTypeDefinition == typeof(Tuple<>) ||
+ genericTypeDefinition == typeof(Tuple<,>) ||
+ genericTypeDefinition == typeof(Tuple<,,>) ||
+ genericTypeDefinition == typeof(Tuple<,,,>) ||
+ genericTypeDefinition == typeof(Tuple<,,,,>) ||
+ genericTypeDefinition == typeof(Tuple<,,,,,>) ||
+ genericTypeDefinition == typeof(Tuple<,,,,,,>) ||
+ genericTypeDefinition == typeof(Tuple<,,,,,,,>);
+ }
+
+ private static object GenerateKeyValuePair(Type keyValuePairType, Dictionary createdObjectReferences)
+ {
+ Type[] genericArgs = keyValuePairType.GetGenericArguments();
+ Type typeK = genericArgs[0];
+ Type typeV = genericArgs[1];
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ object keyObject = objectGenerator.GenerateObject(typeK, createdObjectReferences);
+ object valueObject = objectGenerator.GenerateObject(typeV, createdObjectReferences);
+ if (keyObject == null && valueObject == null)
+ {
+ // Failed to create key and values
+ return null;
+ }
+ object result = Activator.CreateInstance(keyValuePairType, keyObject, valueObject);
+ return result;
+ }
+
+ private static object GenerateArray(Type arrayType, int size, Dictionary createdObjectReferences)
+ {
+ Type type = arrayType.GetElementType();
+ Array result = Array.CreateInstance(type, size);
+ bool areAllElementsNull = true;
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ for (int i = 0; i < size; i++)
+ {
+ object element = objectGenerator.GenerateObject(type, createdObjectReferences);
+ result.SetValue(element, i);
+ areAllElementsNull &= element == null;
+ }
+
+ if (areAllElementsNull)
+ {
+ return null;
+ }
+
+ return result;
+ }
+
+ private static object GenerateDictionary(Type dictionaryType, int size, Dictionary createdObjectReferences)
+ {
+ Type typeK = typeof(object);
+ Type typeV = typeof(object);
+ if (dictionaryType.IsGenericType)
+ {
+ Type[] genericArgs = dictionaryType.GetGenericArguments();
+ typeK = genericArgs[0];
+ typeV = genericArgs[1];
+ }
+
+ object result = Activator.CreateInstance(dictionaryType);
+ MethodInfo addMethod = dictionaryType.GetMethod("Add") ?? dictionaryType.GetMethod("TryAdd");
+ MethodInfo containsMethod = dictionaryType.GetMethod("Contains") ?? dictionaryType.GetMethod("ContainsKey");
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ for (int i = 0; i < size; i++)
+ {
+ object newKey = objectGenerator.GenerateObject(typeK, createdObjectReferences);
+ if (newKey == null)
+ {
+ // Cannot generate a valid key
+ return null;
+ }
+
+ bool containsKey = (bool)containsMethod.Invoke(result, new object[] { newKey });
+ if (!containsKey)
+ {
+ object newValue = objectGenerator.GenerateObject(typeV, createdObjectReferences);
+ addMethod.Invoke(result, new object[] { newKey, newValue });
+ }
+ }
+
+ return result;
+ }
+
+ private static object GenerateEnum(Type enumType)
+ {
+ Array possibleValues = Enum.GetValues(enumType);
+ if (possibleValues.Length > 0)
+ {
+ return possibleValues.GetValue(0);
+ }
+ return null;
+ }
+
+ private static object GenerateQueryable(Type queryableType, int size, Dictionary createdObjectReferences)
+ {
+ bool isGeneric = queryableType.IsGenericType;
+ object list;
+ if (isGeneric)
+ {
+ Type listType = typeof(List<>).MakeGenericType(queryableType.GetGenericArguments());
+ list = GenerateCollection(listType, size, createdObjectReferences);
+ }
+ else
+ {
+ list = GenerateArray(typeof(object[]), size, createdObjectReferences);
+ }
+ if (list == null)
+ {
+ return null;
+ }
+ if (isGeneric)
+ {
+ Type argumentType = typeof(IEnumerable<>).MakeGenericType(queryableType.GetGenericArguments());
+ MethodInfo asQueryableMethod = typeof(Queryable).GetMethod("AsQueryable", new[] { argumentType });
+ return asQueryableMethod.Invoke(null, new[] { list });
+ }
+
+ return Queryable.AsQueryable((IEnumerable)list);
+ }
+
+ private static object GenerateCollection(Type collectionType, int size, Dictionary createdObjectReferences)
+ {
+ Type type = collectionType.IsGenericType ?
+ collectionType.GetGenericArguments()[0] :
+ typeof(object);
+ object result = Activator.CreateInstance(collectionType);
+ MethodInfo addMethod = collectionType.GetMethod("Add");
+ bool areAllElementsNull = true;
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ for (int i = 0; i < size; i++)
+ {
+ object element = objectGenerator.GenerateObject(type, createdObjectReferences);
+ addMethod.Invoke(result, new object[] { element });
+ areAllElementsNull &= element == null;
+ }
+
+ if (areAllElementsNull)
+ {
+ return null;
+ }
+
+ return result;
+ }
+
+ private static object GenerateNullable(Type nullableType, Dictionary createdObjectReferences)
+ {
+ Type type = nullableType.GetGenericArguments()[0];
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ return objectGenerator.GenerateObject(type, createdObjectReferences);
+ }
+
+ private static object GenerateComplexObject(Type type, Dictionary createdObjectReferences)
+ {
+ object result = null;
+
+ if (createdObjectReferences.TryGetValue(type, out result))
+ {
+ // The object has been created already, just return it. This will handle the circular reference case.
+ return result;
+ }
+
+ if (type.IsValueType)
+ {
+ result = Activator.CreateInstance(type);
+ }
+ else
+ {
+ ConstructorInfo defaultCtor = type.GetConstructor(Type.EmptyTypes);
+ if (defaultCtor == null)
+ {
+ // Cannot instantiate the type because it doesn't have a default constructor
+ return null;
+ }
+
+ result = defaultCtor.Invoke(new object[0]);
+ }
+ createdObjectReferences.Add(type, result);
+ SetPublicProperties(type, result, createdObjectReferences);
+ SetPublicFields(type, result, createdObjectReferences);
+ return result;
+ }
+
+ private static void SetPublicProperties(Type type, object obj, Dictionary createdObjectReferences)
+ {
+ PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ foreach (PropertyInfo property in properties)
+ {
+ if (property.CanWrite)
+ {
+ object propertyValue = objectGenerator.GenerateObject(property.PropertyType, createdObjectReferences);
+ property.SetValue(obj, propertyValue, null);
+ }
+ }
+ }
+
+ private static void SetPublicFields(Type type, object obj, Dictionary createdObjectReferences)
+ {
+ FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
+ ObjectGenerator objectGenerator = new ObjectGenerator();
+ foreach (FieldInfo field in fields)
+ {
+ object fieldValue = objectGenerator.GenerateObject(field.FieldType, createdObjectReferences);
+ field.SetValue(obj, fieldValue);
+ }
+ }
+
+ private class SimpleTypeObjectGenerator
+ {
+ private long _index = 0;
+ private static readonly Dictionary> DefaultGenerators = InitializeGenerators();
+
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These are simple type factories and cannot be split up.")]
+ private static Dictionary> InitializeGenerators()
+ {
+ return new Dictionary>
+ {
+ { typeof(Boolean), index => true },
+ { typeof(Byte), index => (Byte)64 },
+ { typeof(Char), index => (Char)65 },
+ { typeof(DateTime), index => DateTime.Now },
+ { typeof(DateTimeOffset), index => new DateTimeOffset(DateTime.Now) },
+ { typeof(DBNull), index => DBNull.Value },
+ { typeof(Decimal), index => (Decimal)index },
+ { typeof(Double), index => (Double)(index + 0.1) },
+ { typeof(Guid), index => Guid.NewGuid() },
+ { typeof(Int16), index => (Int16)(index % Int16.MaxValue) },
+ { typeof(Int32), index => (Int32)(index % Int32.MaxValue) },
+ { typeof(Int64), index => (Int64)index },
+ { typeof(Object), index => new object() },
+ { typeof(SByte), index => (SByte)64 },
+ { typeof(Single), index => (Single)(index + 0.1) },
+ {
+ typeof(String), index =>
+ {
+ return String.Format(CultureInfo.CurrentCulture, "sample string {0}", index);
+ }
+ },
+ {
+ typeof(TimeSpan), index =>
+ {
+ return TimeSpan.FromTicks(1234567);
+ }
+ },
+ { typeof(UInt16), index => (UInt16)(index % UInt16.MaxValue) },
+ { typeof(UInt32), index => (UInt32)(index % UInt32.MaxValue) },
+ { typeof(UInt64), index => (UInt64)index },
+ {
+ typeof(Uri), index =>
+ {
+ return new Uri(String.Format(CultureInfo.CurrentCulture, "http://webapihelppage{0}.com", index));
+ }
+ },
+ };
+ }
+
+ public static bool CanGenerateObject(Type type)
+ {
+ return DefaultGenerators.ContainsKey(type);
+ }
+
+ public object GenerateObject(Type type)
+ {
+ return DefaultGenerators[type](++_index);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/SampleDirection.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/SampleDirection.cs
new file mode 100644
index 0000000..54f09c1
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/SampleDirection.cs
@@ -0,0 +1,11 @@
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// Indicates whether the sample is used for request or response
+ ///
+ public enum SampleDirection
+ {
+ Request = 0,
+ Response
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/TextSample.cs b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/TextSample.cs
new file mode 100644
index 0000000..45463b4
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/SampleGeneration/TextSample.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// This represents a preformatted text sample on the help page. There's a display template named TextSample associated with this class.
+ ///
+ public class TextSample
+ {
+ public TextSample(string text)
+ {
+ if (text == null)
+ {
+ throw new ArgumentNullException("text");
+ }
+ Text = text;
+ }
+
+ public string Text { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ TextSample other = obj as TextSample;
+ return other != null && Text == other.Text;
+ }
+
+ public override int GetHashCode()
+ {
+ return Text.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return Text;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/Api.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/Api.cshtml
new file mode 100644
index 0000000..3b972cc
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/Api.cshtml
@@ -0,0 +1,25 @@
+@using System.Web.Http
+@using EFMVC.Web.API.Areas.HelpPage.Models
+@model HelpPageApiModel
+
+@{
+ var description = Model.ApiDescription;
+ ViewBag.Title = description.HttpMethod.Method + " " + description.RelativePath;
+}
+
+
+
+
+
+ @Html.ActionLink("Help Page Home", "Index")
+
+
+
+
+ @Html.DisplayFor(m => Model)
+
+
+
+@section Scripts {
+
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ApiGroup.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ApiGroup.cshtml
new file mode 100644
index 0000000..e503283
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ApiGroup.cshtml
@@ -0,0 +1,30 @@
+@using System.Web.Http
+@using System.Web.Http.Description
+@using EFMVC.Web.API.Areas.HelpPage
+@using EFMVC.Web.API.Areas.HelpPage.Models
+@model IGrouping
+
+@Model.Key
+
+
+ API Description
+
+
+ @foreach (var api in Model)
+ {
+
+ @api.HttpMethod.Method @api.RelativePath
+
+ @if (api.Documentation != null)
+ {
+ @api.Documentation
+ }
+ else
+ {
+ No documentation available.
+ }
+
+
+ }
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/HelpPageApiModel.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/HelpPageApiModel.cshtml
new file mode 100644
index 0000000..f5c6fd2
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/HelpPageApiModel.cshtml
@@ -0,0 +1,43 @@
+@using System.Web.Http
+@using EFMVC.Web.API.Areas.HelpPage.Models
+@model HelpPageApiModel
+
+@{
+ var description = Model.ApiDescription;
+ bool hasParameters = description.ParameterDescriptions.Count > 0;
+ bool hasRequestSamples = Model.SampleRequests.Count > 0;
+ bool hasResponseSamples = Model.SampleResponses.Count > 0;
+}
+@description.HttpMethod.Method @description.RelativePath
+
+ @if (description.Documentation != null)
+ {
+
@description.Documentation
+ }
+ else
+ {
+
No documentation available.
+ }
+
+ @if (hasParameters || hasRequestSamples)
+ {
+
Request Information
+ if (hasParameters)
+ {
+
Parameters
+ @Html.DisplayFor(apiModel => apiModel.ApiDescription.ParameterDescriptions, "Parameters")
+ }
+ if (hasRequestSamples)
+ {
+
Request body formats
+ @Html.DisplayFor(apiModel => apiModel.SampleRequests, "Samples")
+ }
+ }
+
+ @if (hasResponseSamples)
+ {
+
Response Information
+
Response body formats
+ @Html.DisplayFor(apiModel => apiModel.SampleResponses, "Samples")
+ }
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ImageSample.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ImageSample.cshtml
new file mode 100644
index 0000000..74a1b37
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/ImageSample.cshtml
@@ -0,0 +1,4 @@
+@using EFMVC.Web.API.Areas.HelpPage
+@model ImageSample
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/InvalidSample.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/InvalidSample.cshtml
new file mode 100644
index 0000000..508b2ac
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/InvalidSample.cshtml
@@ -0,0 +1,13 @@
+@using EFMVC.Web.API.Areas.HelpPage
+@model InvalidSample
+
+@if (HttpContext.Current.IsDebuggingEnabled)
+{
+
+}
+else
+{
+ Sample not available.
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Parameters.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Parameters.cshtml
new file mode 100644
index 0000000..6023df6
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Parameters.cshtml
@@ -0,0 +1,42 @@
+@using System.Collections.ObjectModel
+@using System.Web.Http.Description
+@using System.Threading
+@model Collection
+
+
+
+ Name Description Additional information
+
+
+ @foreach (ApiParameterDescription parameter in Model)
+ {
+ string parameterDocumentation = parameter.Documentation != null ?
+ parameter.Documentation :
+ "No documentation available.";
+
+ // Don't show CancellationToken because it's a special parameter
+ if (!typeof(CancellationToken).IsAssignableFrom(parameter.ParameterDescriptor.ParameterType))
+ {
+
+ @parameter.Name
+ @parameterDocumentation
+
+ @switch (parameter.Source)
+ {
+ case ApiParameterSource.FromBody:
+ Define this parameter in the request body .
+ break;
+ case ApiParameterSource.FromUri:
+ Define this parameter in the request URI .
+ break;
+ case ApiParameterSource.Unknown:
+ default:
+ None.
+ break;
+ }
+
+
+ }
+ }
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Samples.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Samples.cshtml
new file mode 100644
index 0000000..c19596f
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/Samples.cshtml
@@ -0,0 +1,30 @@
+@using System.Net.Http.Headers
+@model Dictionary
+
+@{
+ // Group the samples into a single tab if they are the same.
+ Dictionary samples = Model.GroupBy(pair => pair.Value).ToDictionary(
+ pair => String.Join(", ", pair.Select(m => m.Key.ToString()).ToArray()),
+ pair => pair.Key);
+ var mediaTypes = samples.Keys;
+}
+
+ @foreach (var mediaType in mediaTypes)
+ {
+
+
+
Sample:
+ @{
+ var sample = samples[mediaType];
+ if (sample == null)
+ {
+
Sample not available.
+ }
+ else
+ {
+ @Html.DisplayFor(s => sample);
+ }
+ }
+
+ }
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/TextSample.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/TextSample.cshtml
new file mode 100644
index 0000000..00e8bb7
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/DisplayTemplates/TextSample.cshtml
@@ -0,0 +1,6 @@
+@using EFMVC.Web.API.Areas.HelpPage
+@model TextSample
+
+
+@Model.Text
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Help/Index.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Help/Index.cshtml
new file mode 100644
index 0000000..969073d
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Help/Index.cshtml
@@ -0,0 +1,40 @@
+@using System.Web.Http
+@using System.Web.Http.Description
+@using System.Collections.ObjectModel
+@using EFMVC.Web.API.Areas.HelpPage.Models
+@model Collection
+
+@{
+ ViewBag.Title = "ASP.NET Web API Help Page";
+
+ // Group APIs by controller
+ ILookup apiGroups = Model.ToLookup(api => api.ActionDescriptor.ControllerDescriptor.ControllerName);
+}
+
+
+
+
+
+
Introduction
+
+ Provide a general description of your APIs here.
+
+
+
+
+ @foreach (var group in apiGroups)
+ {
+ @Html.DisplayFor(m => group, "ApiGroup")
+ }
+
+
+
+@section Scripts {
+
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Shared/_Layout.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/Shared/_Layout.cshtml
new file mode 100644
index 0000000..bc2e96f
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Shared/_Layout.cshtml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ @ViewBag.Title
+ @RenderSection("scripts", required: false)
+
+
+ @RenderBody()
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/Web.config b/EFMVC.Web.API/Areas/HelpPage/Views/Web.config
new file mode 100644
index 0000000..4794f5c
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/Web.config
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EFMVC.Web.API/Areas/HelpPage/Views/_ViewStart.cshtml b/EFMVC.Web.API/Areas/HelpPage/Views/_ViewStart.cshtml
new file mode 100644
index 0000000..7184d34
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/Views/_ViewStart.cshtml
@@ -0,0 +1,4 @@
+@{
+ // Change the Layout path below to blend the look and feel of the help page with your existing web pages.
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
diff --git a/EFMVC.Web.API/Areas/HelpPage/XmlDocumentationProvider.cs b/EFMVC.Web.API/Areas/HelpPage/XmlDocumentationProvider.cs
new file mode 100644
index 0000000..d3d12a5
--- /dev/null
+++ b/EFMVC.Web.API/Areas/HelpPage/XmlDocumentationProvider.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Web.Http.Controllers;
+using System.Web.Http.Description;
+using System.Xml.XPath;
+
+namespace EFMVC.Web.API.Areas.HelpPage
+{
+ ///
+ /// A custom that reads the API documentation from an XML documentation file.
+ ///
+ public class XmlDocumentationProvider : IDocumentationProvider
+ {
+ private XPathNavigator _documentNavigator;
+ private const string MethodExpression = "/doc/members/member[@name='M:{0}']";
+ private const string ParameterExpression = "param[@name='{0}']";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The physical path to XML document.
+ public XmlDocumentationProvider(string documentPath)
+ {
+ if (documentPath == null)
+ {
+ throw new ArgumentNullException("documentPath");
+ }
+ XPathDocument xpath = new XPathDocument(documentPath);
+ _documentNavigator = xpath.CreateNavigator();
+ }
+
+ public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
+ {
+ XPathNavigator methodNode = GetMethodNode(actionDescriptor);
+ if (methodNode != null)
+ {
+ XPathNavigator summaryNode = methodNode.SelectSingleNode("summary");
+ if (summaryNode != null)
+ {
+ return summaryNode.Value.Trim();
+ }
+ }
+
+ return null;
+ }
+
+ public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
+ {
+ ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
+ if (reflectedParameterDescriptor != null)
+ {
+ XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
+ if (methodNode != null)
+ {
+ string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
+ XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
+ if (parameterNode != null)
+ {
+ return parameterNode.Value.Trim();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor)
+ {
+ ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
+ if (reflectedActionDescriptor != null)
+ {
+ string selectExpression = String.Format(CultureInfo.InvariantCulture, MethodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
+ return _documentNavigator.SelectSingleNode(selectExpression);
+ }
+
+ return null;
+ }
+
+ private static string GetMemberName(MethodInfo method)
+ {
+ string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", method.DeclaringType.FullName, method.Name);
+ ParameterInfo[] parameters = method.GetParameters();
+ if (parameters.Length != 0)
+ {
+ string[] parameterTypeNames = parameters.Select(param => GetTypeName(param.ParameterType)).ToArray();
+ name += String.Format(CultureInfo.InvariantCulture, "({0})", String.Join(",", parameterTypeNames));
+ }
+
+ return name;
+ }
+
+ private static string GetTypeName(Type type)
+ {
+ if (type.IsGenericType)
+ {
+ // Format the generic type name to something like: Generic{System.Int32,System.String}
+ Type genericType = type.GetGenericTypeDefinition();
+ Type[] genericArguments = type.GetGenericArguments();
+ string typeName = genericType.FullName;
+
+ // Trim the generic parameter counts from the name
+ typeName = typeName.Substring(0, typeName.IndexOf('`'));
+ string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray();
+ return String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", typeName, String.Join(",", argumentTypeNames));
+ }
+
+ return type.FullName;
+ }
+ }
+}
diff --git a/EFMVC.Web.API/Bootstrapper.cs b/EFMVC.Web.API/Bootstrapper.cs
new file mode 100644
index 0000000..5dac72b
--- /dev/null
+++ b/EFMVC.Web.API/Bootstrapper.cs
@@ -0,0 +1,42 @@
+using System.Web.Mvc;
+using Autofac;
+using Autofac.Integration.WebApi;
+using System.Reflection;
+using EFMVC.CommandProcessor.Command;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Data.Infrastructure;
+using EFMVC.Data.Repositories;
+using System.Web.Http;
+namespace EFMVC.Web.API
+{
+ public static class Bootstrapper
+ {
+ public static void Run()
+ {
+
+ SetAutofacWebAPIServices();
+ }
+ private static void SetAutofacWebAPIServices()
+ {
+ var configuration = GlobalConfiguration.Configuration;
+ var builder = new ContainerBuilder();
+ // Register API controllers using assembly scanning.
+ builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
+ builder.RegisterType().As().InstancePerApiRequest();
+ builder.RegisterType().As().InstancePerApiRequest();
+ builder.RegisterType().As().InstancePerApiRequest();
+ builder.RegisterAssemblyTypes(typeof(CategoryRepository)
+ .Assembly).Where(t => t.Name.EndsWith("Repository"))
+ .AsImplementedInterfaces().InstancePerApiRequest();
+ var services = Assembly.Load("EFMVC.Domain");
+ builder.RegisterAssemblyTypes(services)
+ .AsClosedTypesOf(typeof(ICommandHandler<>)).InstancePerApiRequest();
+ builder.RegisterAssemblyTypes(services)
+ .AsClosedTypesOf(typeof(IValidationHandler<>)).InstancePerApiRequest();
+ var container = builder.Build();
+ // Set the dependency resolver implementation.
+ var resolver = new AutofacWebApiDependencyResolver(container);
+ configuration.DependencyResolver = resolver;
+ }
+ }
+}
diff --git a/EFMVC.Web.API/Content/Site.css b/EFMVC.Web.API/Content/Site.css
new file mode 100644
index 0000000..be14409
--- /dev/null
+++ b/EFMVC.Web.API/Content/Site.css
@@ -0,0 +1,756 @@
+html {
+ background-color: #e2e2e2;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ background-color: #fff;
+ border-top: solid 10px #000;
+ color: #333;
+ font-size: .85em;
+ font-family: "Segoe UI", Verdana, Helvetica, Sans-Serif;
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #333;
+ outline: none;
+ padding-left: 3px;
+ padding-right: 3px;
+ text-decoration: underline;
+}
+
+ a:link, a:visited,
+ a:active, a:hover {
+ color: #333;
+ }
+
+ a:hover {
+ background-color: #c7d1d6;
+ }
+
+header, footer, hgroup,
+nav, section {
+ display: block;
+}
+
+mark {
+ background-color: #a6dbed;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.float-left {
+ float: left;
+}
+
+.float-right {
+ float: right;
+}
+
+.clear-fix:after {
+ content: ".";
+ clear: both;
+ display: block;
+ height: 0;
+ visibility: hidden;
+}
+
+h1, h2, h3,
+h4, h5, h6 {
+ color: #000;
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+
+h1 {
+ font-size: 2em;
+}
+
+h2 {
+ font-size: 1.75em;
+}
+
+h3 {
+ font-size: 1.2em;
+}
+
+h4 {
+ font-size: 1.1em;
+}
+
+h5, h6 {
+ font-size: 1em;
+}
+
+ h5 a:link, h5 a:visited, h5 a:active {
+ padding: 0;
+ text-decoration: none;
+ }
+
+
+/* main layout
+----------------------------------------------------------*/
+.content-wrapper {
+ margin: 0 auto;
+ max-width: 960px;
+}
+
+#body {
+ background-color: #efeeef;
+ clear: both;
+ padding-bottom: 35px;
+}
+
+ .main-content {
+ background: url("../Images/accent.png") no-repeat;
+ padding-left: 10px;
+ padding-top: 30px;
+ }
+
+ .featured + .main-content {
+ background: url("../Images/heroAccent.png") no-repeat;
+ }
+
+header .content-wrapper {
+ padding-top: 20px;
+}
+
+footer {
+ clear: both;
+ background-color: #e2e2e2;
+ font-size: .8em;
+ height: 100px;
+}
+
+
+/* site title
+----------------------------------------------------------*/
+.site-title {
+ color: #c8c8c8;
+ font-family: Rockwell, Consolas, "Courier New", Courier, monospace;
+ font-size: 2.3em;
+ margin: 0;
+}
+
+.site-title a, .site-title a:hover, .site-title a:active {
+ background: none;
+ color: #c8c8c8;
+ outline: none;
+ text-decoration: none;
+}
+
+
+/* login
+----------------------------------------------------------*/
+#login {
+ display: block;
+ font-size: .85em;
+ margin: 0 0 10px;
+ text-align: right;
+}
+
+ #login a {
+ background-color: #d3dce0;
+ margin-left: 10px;
+ margin-right: 3px;
+ padding: 2px 3px;
+ text-decoration: none;
+ }
+
+ #login a.username {
+ background: none;
+ margin: 0;
+ padding: 0;
+ text-decoration: underline;
+ }
+
+ #login ul {
+ margin: 0;
+ }
+
+ #login li {
+ display: inline;
+ list-style: none;
+ }
+
+
+/* menu
+----------------------------------------------------------*/
+ul#menu {
+ font-size: 1.3em;
+ font-weight: 600;
+ margin: 0 0 5px;
+ padding: 0;
+ text-align: right;
+}
+
+ ul#menu li {
+ display: inline;
+ list-style: none;
+ padding-left: 15px;
+ }
+
+ ul#menu li a {
+ background: none;
+ color: #999;
+ text-decoration: none;
+ }
+
+ ul#menu li a:hover {
+ color: #333;
+ text-decoration: none;
+ }
+
+
+/* page elements
+----------------------------------------------------------*/
+/* featured */
+.featured {
+ background-color: #fff;
+}
+
+ .featured .content-wrapper {
+ background-color: #7ac0da;
+ background-image: -ms-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: -o-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: -webkit-gradient(linear, left top, right top, color-stop(0, #7ac0da), color-stop(1, #a4d4e6));
+ background-image: -webkit-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ color: #3e5667;
+ padding: 20px 40px 30px 40px;
+ }
+
+ .featured hgroup.title h1, .featured hgroup.title h2 {
+ color: #fff;
+ }
+
+ .featured p {
+ font-size: 1.1em;
+ }
+
+/* page titles */
+hgroup.title {
+ margin-bottom: 10px;
+}
+
+hgroup.title h1, hgroup.title h2 {
+ display: inline;
+}
+
+hgroup.title h2 {
+ font-weight: normal;
+ margin-left: 3px;
+}
+
+/* features */
+section.feature {
+ width: 300px;
+ float: left;
+ padding: 10px;
+}
+
+/* ordered list */
+ol.round {
+ list-style-type: none;
+ padding-left: 0;
+}
+
+ ol.round li {
+ margin: 25px 0;
+ padding-left: 45px;
+ }
+
+ ol.round li.zero {
+ background: url("../Images/orderedList0.png") no-repeat;
+ }
+
+ ol.round li.one {
+ background: url("../Images/orderedList1.png") no-repeat;
+ }
+
+ ol.round li.two {
+ background: url("../Images/orderedList2.png") no-repeat;
+ }
+
+ ol.round li.three {
+ background: url("../Images/orderedList3.png") no-repeat;
+ }
+
+ ol.round li.four {
+ background: url("../Images/orderedList4.png") no-repeat;
+ }
+
+ ol.round li.five {
+ background: url("../Images/orderedList5.png") no-repeat;
+ }
+
+ ol.round li.six {
+ background: url("../Images/orderedList6.png") no-repeat;
+ }
+
+ ol.round li.seven {
+ background: url("../Images/orderedList7.png") no-repeat;
+ }
+
+ ol.round li.eight {
+ background: url("../Images/orderedList8.png") no-repeat;
+ }
+
+ ol.round li.nine {
+ background: url("../Images/orderedList9.png") no-repeat;
+ }
+
+/* content */
+article {
+ float: left;
+ width: 70%;
+}
+
+aside {
+ float: right;
+ width: 25%;
+}
+
+ aside ul {
+ list-style: none;
+ padding: 0;
+ }
+
+ aside ul li {
+ background: url("../Images/bullet.png") no-repeat 0 50%;
+ padding: 2px 0 2px 20px;
+ }
+
+.label {
+ font-weight: 700;
+}
+
+/* login page */
+#loginForm {
+ border-right: solid 2px #c8c8c8;
+ float: left;
+ width: 55%;
+}
+
+ #loginForm .validation-error {
+ display: block;
+ margin-left: 15px;
+ }
+
+ #loginForm .validation-summary-errors ul {
+ margin: 0;
+ padding: 0;
+ }
+
+ #loginForm .validation-summary-errors li {
+ display: inline;
+ list-style: none;
+ margin: 0;
+ }
+
+ #loginForm input {
+ width: 250px;
+ }
+
+ #loginForm input[type="checkbox"],
+ #loginForm input[type="submit"],
+ #loginForm input[type="button"],
+ #loginForm button {
+ width: auto;
+ }
+
+#socialLoginForm {
+ margin-left: 40px;
+ float: left;
+ width: 40%;
+}
+
+ #socialLoginForm h2 {
+ margin-bottom: 5px;
+ }
+
+#socialLoginList button {
+ margin-bottom: 12px;
+}
+
+#logoutForm {
+ display: inline;
+}
+
+/* contact */
+.contact h3 {
+ font-size: 1.2em;
+}
+
+.contact p {
+ margin: 5px 0 0 10px;
+}
+
+.contact iframe {
+ border: 1px solid #333;
+ margin: 5px 0 0 10px;
+}
+
+/* forms */
+fieldset {
+ border: none;
+ margin: 0;
+ padding: 0;
+}
+
+ fieldset legend {
+ display: none;
+ }
+
+ fieldset ol {
+ padding: 0;
+ list-style: none;
+ }
+
+ fieldset ol li {
+ padding-bottom: 5px;
+ }
+
+label {
+ display: block;
+ font-size: 1.2em;
+ font-weight: 600;
+}
+
+label.checkbox {
+ display: inline;
+}
+
+input, textarea {
+ border: 1px solid #e2e2e2;
+ background: #fff;
+ color: #333;
+ font-size: 1.2em;
+ margin: 5px 0 6px 0;
+ padding: 5px;
+ width: 300px;
+}
+
+textarea {
+ font-family: inherit;
+ width: 500px;
+}
+
+ input:focus, textarea:focus {
+ border: 1px solid #7ac0da;
+ }
+
+ input[type="checkbox"] {
+ background: transparent;
+ border: inherit;
+ width: auto;
+ }
+
+ input[type="submit"],
+ input[type="button"],
+ button {
+ background-color: #d3dce0;
+ border: 1px solid #787878;
+ cursor: pointer;
+ font-size: 1.2em;
+ font-weight: 600;
+ padding: 7px;
+ margin-right: 8px;
+ width: auto;
+ }
+
+ td input[type="submit"],
+ td input[type="button"],
+ td button {
+ font-size: 1em;
+ padding: 4px;
+ margin-right: 4px;
+ }
+
+/* info and errors */
+.message-info {
+ border: 1px solid;
+ clear: both;
+ padding: 10px 20px;
+}
+
+.message-error {
+ clear: both;
+ color: #e80c4d;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin: 20px 0 10px 0;
+}
+
+.message-success {
+ color: #7ac0da;
+ font-size: 1.3em;
+ font-weight: bold;
+ margin: 20px 0 10px 0;
+}
+
+.error {
+ color: #e80c4d;
+}
+
+/* styles for validation helpers */
+.field-validation-error {
+ color: #e80c4d;
+ font-weight: bold;
+}
+
+.field-validation-valid {
+ display: none;
+}
+
+input.input-validation-error {
+ border: 1px solid #e80c4d;
+}
+
+input[type="checkbox"].input-validation-error {
+ border: 0 none;
+}
+
+.validation-summary-errors {
+ color: #e80c4d;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.validation-summary-valid {
+ display: none;
+}
+
+
+/* tables
+----------------------------------------------------------*/
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ margin-top: 0.75em;
+ border: 0 none;
+}
+
+th {
+ font-size: 1.2em;
+ text-align: left;
+ border: none 0px;
+ padding-left: 0;
+}
+
+ th a {
+ display: block;
+ position: relative;
+ }
+
+ th a:link, th a:visited, th a:active, th a:hover {
+ color: #333;
+ font-weight: 600;
+ text-decoration: none;
+ padding: 0;
+ }
+
+ th a:hover {
+ color: #000;
+ }
+
+ th.asc a, th.desc a {
+ margin-right: .75em;
+ }
+
+ th.asc a:after, th.desc a:after {
+ display: block;
+ position: absolute;
+ right: 0em;
+ top: 0;
+ font-size: 0.75em;
+ }
+
+ th.asc a:after {
+ content: '▲';
+ }
+
+ th.desc a:after {
+ content: '▼';
+ }
+
+td {
+ padding: 0.25em 2em 0.25em 0em;
+ border: 0 none;
+}
+
+tr.pager td {
+ padding: 0 0.25em 0 0;
+}
+
+
+/********************
+* Mobile Styles *
+********************/
+@media only screen and (max-width: 850px) {
+
+ /* header
+ ----------------------------------------------------------*/
+ header .float-left,
+ header .float-right {
+ float: none;
+ }
+
+ /* logo */
+ header .site-title {
+ margin: 10px;
+ text-align: center;
+ }
+
+ /* login */
+ #login {
+ font-size: .85em;
+ margin: 0 0 12px;
+ text-align: center;
+ }
+
+ #login ul {
+ margin: 5px 0;
+ padding: 0;
+ }
+
+ #login li {
+ display: inline;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ #login a {
+ background: none;
+ color: #999;
+ font-weight: 600;
+ margin: 2px;
+ padding: 0;
+ }
+
+ #login a:hover {
+ color: #333;
+ }
+
+ /* menu */
+ nav {
+ margin-bottom: 5px;
+ }
+
+ ul#menu {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ }
+
+ ul#menu li {
+ margin: 0;
+ padding: 0;
+ }
+
+
+ /* main layout
+ ----------------------------------------------------------*/
+ .main-content,
+ .featured + .main-content {
+ background-position: 10px 0;
+ }
+
+ .content-wrapper {
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+
+ .featured .content-wrapper {
+ padding: 10px;
+ }
+
+ /* page content */
+ article, aside {
+ float: none;
+ width: 100%;
+ }
+
+ /* ordered list */
+ ol.round {
+ list-style-type: none;
+ padding-left: 0;
+ }
+
+ ol.round li {
+ padding-left: 10px;
+ margin: 25px 0;
+ }
+
+ ol.round li.zero,
+ ol.round li.one,
+ ol.round li.two,
+ ol.round li.three,
+ ol.round li.four,
+ ol.round li.five,
+ ol.round li.six,
+ ol.round li.seven,
+ ol.round li.eight,
+ ol.round li.nine {
+ background: none;
+ }
+
+ /* features */
+ section.feature {
+ float: none;
+ padding: 10px;
+ width: auto;
+ }
+
+ section.feature img {
+ color: #999;
+ content: attr(alt);
+ font-size: 1.5em;
+ font-weight: 600;
+ }
+
+ /* forms */
+ input {
+ width: 90%;
+ }
+
+ /* login page */
+ #loginForm {
+ border-right: none;
+ float: none;
+ width: auto;
+ }
+
+ #loginForm .validation-error {
+ display: block;
+ margin-left: 15px;
+ }
+
+ #socialLoginForm {
+ margin-left: 0;
+ float: none;
+ width: auto;
+ }
+
+
+ /* footer
+ ----------------------------------------------------------*/
+ footer .float-left,
+ footer .float-right {
+ float: none;
+ }
+
+ footer {
+ text-align: center;
+ height: auto;
+ padding: 10px 0;
+ }
+
+ footer p {
+ margin: 0;
+ }
+}
diff --git a/MyFinance.Web/Content/images/ui-bg_flat_0_aaaaaa_40x100.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_flat_0_aaaaaa_40x100.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
diff --git a/MyFinance.Web/Content/images/ui-bg_flat_75_ffffff_40x100.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_flat_75_ffffff_40x100.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_55_fbf9ee_1x400.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_glass_55_fbf9ee_1x400.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_65_ffffff_1x400.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_glass_65_ffffff_1x400.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_75_dadada_1x400.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_glass_75_dadada_1x400.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_75_dadada_1x400.png
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_75_e6e6e6_1x400.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_glass_75_e6e6e6_1x400.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_95_fef1ec_1x400.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_glass_95_fef1ec_1x400.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
diff --git a/MyFinance.Web/Content/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/EFMVC.Web.API/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-bg_highlight-soft_75_cccccc_1x100.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
diff --git a/MyFinance.Web/Content/images/ui-icons_222222_256x240.png b/EFMVC.Web.API/Content/themes/base/images/ui-icons_222222_256x240.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-icons_222222_256x240.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-icons_222222_256x240.png
diff --git a/MyFinance.Web/Content/images/ui-icons_2e83ff_256x240.png b/EFMVC.Web.API/Content/themes/base/images/ui-icons_2e83ff_256x240.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-icons_2e83ff_256x240.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-icons_2e83ff_256x240.png
diff --git a/MyFinance.Web/Content/images/ui-icons_454545_256x240.png b/EFMVC.Web.API/Content/themes/base/images/ui-icons_454545_256x240.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-icons_454545_256x240.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-icons_454545_256x240.png
diff --git a/MyFinance.Web/Content/images/ui-icons_888888_256x240.png b/EFMVC.Web.API/Content/themes/base/images/ui-icons_888888_256x240.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-icons_888888_256x240.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-icons_888888_256x240.png
diff --git a/MyFinance.Web/Content/images/ui-icons_cd0a0a_256x240.png b/EFMVC.Web.API/Content/themes/base/images/ui-icons_cd0a0a_256x240.png
similarity index 100%
rename from MyFinance.Web/Content/images/ui-icons_cd0a0a_256x240.png
rename to EFMVC.Web.API/Content/themes/base/images/ui-icons_cd0a0a_256x240.png
diff --git a/EFMVC.Web.API/Content/themes/base/jquery-ui.css b/EFMVC.Web.API/Content/themes/base/jquery-ui.css
new file mode 100644
index 0000000..3f58908
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery-ui.css
@@ -0,0 +1,464 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.tabs.css, jquery.ui.theme.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
+
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.24
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
+.ui-widget-content a { color: #222222/*{fcContent}*/; }
+.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
+.ui-widget-header a { color: #222222/*{fcHeader}*/; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
+.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.accordion.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.accordion.css
new file mode 100644
index 0000000..a3ae969
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.accordion.css
@@ -0,0 +1,19 @@
+/*!
+ * jQuery UI Accordion 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.all.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.all.css
new file mode 100644
index 0000000..dd03bd7
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.all.css
@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming
+ */
+@import "jquery.ui.base.css";
+@import "jquery.ui.theme.css";
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.autocomplete.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.autocomplete.css
new file mode 100644
index 0000000..397ff64
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.autocomplete.css
@@ -0,0 +1,53 @@
+/*!
+ * jQuery UI Autocomplete 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.24
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.base.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.base.css
new file mode 100644
index 0000000..5d71682
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.base.css
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming
+ */
+@import url("jquery.ui.core.css");
+
+@import url("jquery.ui.accordion.css");
+@import url("jquery.ui.autocomplete.css");
+@import url("jquery.ui.button.css");
+@import url("jquery.ui.datepicker.css");
+@import url("jquery.ui.dialog.css");
+@import url("jquery.ui.progressbar.css");
+@import url("jquery.ui.resizable.css");
+@import url("jquery.ui.selectable.css");
+@import url("jquery.ui.slider.css");
+@import url("jquery.ui.tabs.css");
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.button.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.button.css
new file mode 100644
index 0000000..dd24f87
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.button.css
@@ -0,0 +1,38 @@
+/*!
+ * jQuery UI Button 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.core.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.core.css
new file mode 100644
index 0000000..03867e8
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.core.css
@@ -0,0 +1,38 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.datepicker.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.datepicker.css
new file mode 100644
index 0000000..8e6223e
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.datepicker.css
@@ -0,0 +1,66 @@
+/*!
+ * jQuery UI Datepicker 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.dialog.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.dialog.css
new file mode 100644
index 0000000..5460faf
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.dialog.css
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI Dialog 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.progressbar.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.progressbar.css
new file mode 100644
index 0000000..3bc324d
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.progressbar.css
@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Progressbar 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.resizable.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.resizable.css
new file mode 100644
index 0000000..4797f34
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.resizable.css
@@ -0,0 +1,20 @@
+/*!
+ * jQuery UI Resizable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.selectable.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.selectable.css
new file mode 100644
index 0000000..c9fb691
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.selectable.css
@@ -0,0 +1,10 @@
+/*!
+ * jQuery UI Selectable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.slider.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.slider.css
new file mode 100644
index 0000000..b35d87f
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.slider.css
@@ -0,0 +1,24 @@
+/*!
+ * jQuery UI Slider 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.tabs.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.tabs.css
new file mode 100644
index 0000000..0405782
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.tabs.css
@@ -0,0 +1,18 @@
+/*!
+ * jQuery UI Tabs 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/EFMVC.Web.API/Content/themes/base/jquery.ui.theme.css b/EFMVC.Web.API/Content/themes/base/jquery.ui.theme.css
new file mode 100644
index 0000000..6af77c1
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/jquery.ui.theme.css
@@ -0,0 +1,247 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Licensed under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
+.ui-widget-content a { color: #222222/*{fcContent}*/; }
+.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
+.ui-widget-header a { color: #222222/*{fcHeader}*/; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
+.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_0_aaaaaa_40x100.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..5b5dab2
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_75_ffffff_40x100.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000..ac8b229
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_55_fbf9ee_1x400.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000..ad3d634
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_65_ffffff_1x400.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000..42ccba2
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_dadada_1x400.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000..5a46b47
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_e6e6e6_1x400.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000..86c2baa
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_95_fef1ec_1x400.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..4443fdc
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000..7c9fa6c
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/MyFinance.Web/Content/images/ui-icons_ffffff_256x240.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_222222_256x240.png
similarity index 97%
rename from MyFinance.Web/Content/images/ui-icons_ffffff_256x240.png
rename to EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_222222_256x240.png
index bef5178..ee039dc 100644
Binary files a/MyFinance.Web/Content/images/ui-icons_ffffff_256x240.png and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_222222_256x240.png differ
diff --git a/MyFinance.Web/Content/images/ui-icons_ef8c08_256x240.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_2e83ff_256x240.png
similarity index 92%
rename from MyFinance.Web/Content/images/ui-icons_ef8c08_256x240.png
rename to EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_2e83ff_256x240.png
index 35bb8ef..45e8928 100644
Binary files a/MyFinance.Web/Content/images/ui-icons_ef8c08_256x240.png and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_2e83ff_256x240.png differ
diff --git a/MyFinance.Web/Content/images/ui-icons_e9cd86_256x240.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_454545_256x240.png
similarity index 92%
rename from MyFinance.Web/Content/images/ui-icons_e9cd86_256x240.png
rename to EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_454545_256x240.png
index 8cb9c89..7ec70d1 100644
Binary files a/MyFinance.Web/Content/images/ui-icons_e9cd86_256x240.png and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_454545_256x240.png differ
diff --git a/MyFinance.Web/Content/images/ui-icons_070603_256x240.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_888888_256x240.png
similarity index 92%
rename from MyFinance.Web/Content/images/ui-icons_070603_256x240.png
rename to EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_888888_256x240.png
index fb0bf72..5ba708c 100644
Binary files a/MyFinance.Web/Content/images/ui-icons_070603_256x240.png and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_888888_256x240.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_cd0a0a_256x240.png b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..7930a55
Binary files /dev/null and b/EFMVC.Web.API/Content/themes/base/minified/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery-ui.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery-ui.min.css
new file mode 100644
index 0000000..802bc28
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery-ui.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.tabs.css, jquery.ui.theme.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px);clip:rect(1px,1px,1px,1px)}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-accordion{width:100%}.ui-accordion .ui-accordion-header{cursor:pointer;position:relative;margin-top:1px;zoom:1}.ui-accordion .ui-accordion-li-fix{display:inline}.ui-accordion .ui-accordion-header-active{border-bottom:0!important}.ui-accordion .ui-accordion-header a{display:block;font-size:1em;padding:.5em .5em .5em .7em}.ui-accordion-icons .ui-accordion-header a{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;margin-top:-2px;position:relative;top:1px;margin-bottom:2px;overflow:auto;display:none;zoom:1}.ui-accordion .ui-accordion-content-active{display:block}.ui-autocomplete{position:absolute;cursor:default}* html .ui-autocomplete{width:1px}.ui-menu{list-style:none;padding:2px;margin:0;display:block;float:left}.ui-menu .ui-menu{margin-top:-3px}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;float:left;clear:left;width:100%}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:.2em .4em;line-height:1.5;zoom:1}.ui-menu .ui-menu-item a.ui-state-hover,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;text-decoration:none!important;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-dialog{position:absolute;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:1px;margin:0 .2em 1px 0;border-bottom:0!important;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-selected{margin-bottom:0;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-selected a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-state-processing a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tabs .ui-tabs-hide{display:none!important}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-widget:active{outline:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-off{background-position:-96px -144px}.ui-icon-radio-on{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.accordion.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.accordion.min.css
new file mode 100644
index 0000000..161832d
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.accordion.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.accordion.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-accordion{width:100%}.ui-accordion .ui-accordion-header{cursor:pointer;position:relative;margin-top:1px;zoom:1}.ui-accordion .ui-accordion-li-fix{display:inline}.ui-accordion .ui-accordion-header-active{border-bottom:0!important}.ui-accordion .ui-accordion-header a{display:block;font-size:1em;padding:.5em .5em .5em .7em}.ui-accordion-icons .ui-accordion-header a{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;margin-top:-2px;position:relative;top:1px;margin-bottom:2px;overflow:auto;display:none;zoom:1}.ui-accordion .ui-accordion-content-active{display:block}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.autocomplete.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.autocomplete.min.css
new file mode 100644
index 0000000..bed892a
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.autocomplete.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.autocomplete.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-autocomplete{position:absolute;cursor:default}* html .ui-autocomplete{width:1px}.ui-menu{list-style:none;padding:2px;margin:0;display:block;float:left}.ui-menu .ui-menu{margin-top:-3px}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;float:left;clear:left;width:100%}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:.2em .4em;line-height:1.5;zoom:1}.ui-menu .ui-menu-item a.ui-state-hover,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.button.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.button.min.css
new file mode 100644
index 0000000..4c1303c
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.button.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.button.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;text-decoration:none!important;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.core.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.core.min.css
new file mode 100644
index 0000000..53983ce
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.core.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.core.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px);clip:rect(1px,1px,1px,1px)}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.datepicker.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.datepicker.min.css
new file mode 100644
index 0000000..ae5aae5
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.datepicker.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.datepicker.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.dialog.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.dialog.min.css
new file mode 100644
index 0000000..3157754
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.dialog.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.dialog.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-dialog{position:absolute;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.progressbar.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.progressbar.min.css
new file mode 100644
index 0000000..1b34ceb
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.progressbar.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.progressbar.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.resizable.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.resizable.min.css
new file mode 100644
index 0000000..0e781c3
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.resizable.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.resizable.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.selectable.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.selectable.min.css
new file mode 100644
index 0000000..62934b5
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.selectable.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.selectable.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.slider.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.slider.min.css
new file mode 100644
index 0000000..aad334f
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.slider.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.slider.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.tabs.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.tabs.min.css
new file mode 100644
index 0000000..e8a7af5
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.tabs.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.tabs.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:1px;margin:0 .2em 1px 0;border-bottom:0!important;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-selected{margin-bottom:0;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-selected a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-state-processing a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tabs .ui-tabs-hide{display:none!important}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.theme.min.css b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.theme.min.css
new file mode 100644
index 0000000..1437a1e
--- /dev/null
+++ b/EFMVC.Web.API/Content/themes/base/minified/jquery.ui.theme.min.css
@@ -0,0 +1,5 @@
+/*! jQuery UI - v1.8.24 - 2012-09-28
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.theme.css
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT */
+.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-widget:active{outline:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-off{background-position:-96px -144px}.ui-icon-radio-on{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Controllers/CategoryController.cs b/EFMVC.Web.API/Controllers/CategoryController.cs
new file mode 100644
index 0000000..e4be868
--- /dev/null
+++ b/EFMVC.Web.API/Controllers/CategoryController.cs
@@ -0,0 +1,95 @@
+
+using System;
+using System.Linq;
+using System.Net.Http;
+using System.Web.Http;
+using EFMVC.Data.Repositories;
+using System.Net;
+using EFMVC.CommandProcessor.Dispatcher;
+using EFMVC.Domain.Commands;
+using EFMVC.Web.API.Models;
+using EFMVC.Model;
+using System.Collections.Generic;
+namespace EFMVC.Web.API.Controllers
+{
+ //This HTTP service provides the category data with type Category/CategoryWithExpense
+ public class CategoryController : ApiController
+ {
+
+ private readonly ICommandBus commandBus;
+ private readonly ICategoryRepository categoryRepository;
+ public CategoryController(ICommandBus commandBus, ICategoryRepository categoryRepository)
+ {
+ this.commandBus = commandBus;
+ this.categoryRepository = categoryRepository;
+ }
+ public IQueryable Get()
+ {
+ var categories = categoryRepository.GetCategoryWithExpenses().AsQueryable();
+ return categories;
+ }
+
+ // GET /api/category/5
+ public HttpResponseMessage Get(int id)
+ {
+ var category = categoryRepository.GetCategoryWithExpenses().Where(c => c.CategoryId == id).SingleOrDefault();
+ if (category == null)
+ {
+ return Request.CreateResponse(HttpStatusCode.NotFound);
+ }
+ return Request.CreateResponse(HttpStatusCode.OK, category);
+ }
+
+ // POST /api/category
+ public HttpResponseMessage Post(CategoryModel category)
+ {
+
+ if (ModelState.IsValid)
+ {
+ var command = new CreateOrUpdateCategoryCommand(category.CategoryId, category.CategoryName, category.Description);
+ var result = commandBus.Submit(command);
+ if (result.Success)
+ {
+ var response = Request.CreateResponse(HttpStatusCode.Created, category);
+ string uri = Url.Link("DefaultApi", new { id = category.CategoryId });
+ response.Headers.Location = new Uri(uri);
+ return response;
+ }
+ }
+ else
+ {
+ return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
+ }
+ throw new HttpResponseException(HttpStatusCode.BadRequest);
+ }
+
+ // PUT /api/category/5
+ public HttpResponseMessage Put(int id, CategoryModel category)
+ {
+ if (ModelState.IsValid)
+ {
+ var command = new CreateOrUpdateCategoryCommand(category.CategoryId, category.CategoryName, category.Description);
+ var result = commandBus.Submit(command);
+ return Request.CreateResponse(HttpStatusCode.OK, category);
+ }
+ else
+ {
+ return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
+ }
+ throw new HttpResponseException(HttpStatusCode.BadRequest);
+ }
+
+ // DELETE /api/category/5
+ public HttpResponseMessage Delete(int id)
+ {
+ var command = new DeleteCategoryCommand { CategoryId = id };
+ var result = commandBus.Submit(command);
+ if (result.Success)
+ {
+ return new HttpResponseMessage(HttpStatusCode.NoContent);
+ }
+ throw new HttpResponseException(HttpStatusCode.BadRequest);
+ }
+ }
+}
+
diff --git a/MyFinance.Web/Areas/Mobile/Controllers/HomeController.cs b/EFMVC.Web.API/Controllers/HomeController.cs
similarity index 73%
rename from MyFinance.Web/Areas/Mobile/Controllers/HomeController.cs
rename to EFMVC.Web.API/Controllers/HomeController.cs
index bfe1dc5..6c0d723 100644
--- a/MyFinance.Web/Areas/Mobile/Controllers/HomeController.cs
+++ b/EFMVC.Web.API/Controllers/HomeController.cs
@@ -4,17 +4,13 @@
using System.Web;
using System.Web.Mvc;
-namespace MyFinance.Web.Areas.Mobile.Controllers
+namespace EFMVC.Web.API.Controllers
{
public class HomeController : Controller
{
- //
- // GET: /Mobile/Home/
-
public ActionResult Index()
{
return View();
}
-
}
}
diff --git a/EFMVC.Web.API/EFMVC.Web.API.csproj b/EFMVC.Web.API/EFMVC.Web.API.csproj
new file mode 100644
index 0000000..ade3720
--- /dev/null
+++ b/EFMVC.Web.API/EFMVC.Web.API.csproj
@@ -0,0 +1,356 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ 2.0
+ {8739F83B-A769-4FB8-A5B5-D96D640DB716}
+ {E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ EFMVC.Web.API
+ EFMVC.Web.API
+ v4.5
+ false
+ true
+
+
+
+
+
+
+ true
+ full
+ false
+ bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Autofac.3.1.1\lib\net40\Autofac.dll
+
+
+ ..\packages\Autofac.WebApi.3.1.0\lib\net40\Autofac.Integration.WebApi.dll
+
+
+ ..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll
+
+
+ True
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll
+
+
+ ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
+
+
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll
+
+
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll
+
+
+ ..\packages\Microsoft.AspNet.Web.Optimization.1.0.0\lib\net40\System.Web.Optimization.dll
+
+
+ ..\packages\Microsoft.AspNet.Providers.Core.1.2\lib\net40\System.Web.Providers.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebApi.Tracing.4.0.0\lib\net40\System.Web.Http.Tracing.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebApi.OData.4.0.0\lib\net40\System.Web.Http.OData.dll
+
+
+ True
+ ..\packages\Microsoft.Data.Edm.5.2.0\lib\net40\Microsoft.Data.Edm.dll
+
+
+ True
+ ..\packages\Microsoft.Data.OData.5.2.0\lib\net40\Microsoft.Data.OData.dll
+
+
+ True
+ ..\packages\System.Spatial.5.2.0\lib\net40\System.Spatial.dll
+
+
+ True
+ ..\packages\WebGrease.1.3.0\lib\WebGrease.dll
+
+
+ True
+ ..\packages\WebGrease.1.3.0\lib\Antlr3.Runtime.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Global.asax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Web.config
+
+
+ Web.config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {955fd94a-bbc1-4469-889a-740fb98338de}
+ EFMVC.CommandProcessor
+
+
+ {c73d0df7-d21b-4e15-a8aa-70540236d452}
+ EFMVC.Core
+
+
+ {6a4c3b88-230d-4c19-945e-4685876aa31d}
+ EFMVC.Data
+
+
+ {5aa95e73-cbdd-460e-96f9-4a3da709dfe0}
+ EFMVC.Domain
+
+
+ {0cb7b2db-aeca-421a-aa9f-bff8b532d535}
+ EFMVC.Model
+
+
+
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+ /
+ http://localhost:40926/
+ False
+ False
+
+
+ False
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web.API/Global.asax b/EFMVC.Web.API/Global.asax
new file mode 100644
index 0000000..009e61e
--- /dev/null
+++ b/EFMVC.Web.API/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="EFMVC.Web.API.WebApiApplication" Language="C#" %>
diff --git a/EFMVC.Web.API/Global.asax.cs b/EFMVC.Web.API/Global.asax.cs
new file mode 100644
index 0000000..f8fd614
--- /dev/null
+++ b/EFMVC.Web.API/Global.asax.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Http;
+using System.Web.Mvc;
+using System.Web.Optimization;
+using System.Web.Routing;
+
+namespace EFMVC.Web.API
+{
+ // Note: For instructions on enabling IIS6 or IIS7 classic mode,
+ // visit http://go.microsoft.com/?LinkId=9394801
+
+ public class WebApiApplication : System.Web.HttpApplication
+ {
+ protected void Application_Start()
+ {
+ AreaRegistration.RegisterAllAreas();
+
+ WebApiConfig.Register(GlobalConfiguration.Configuration);
+ FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
+ RouteConfig.RegisterRoutes(RouteTable.Routes);
+ BundleConfig.RegisterBundles(BundleTable.Bundles);
+ Bootstrapper.Run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/EFMVC.Web.API/Images/accent.png b/EFMVC.Web.API/Images/accent.png
new file mode 100644
index 0000000..cd07580
Binary files /dev/null and b/EFMVC.Web.API/Images/accent.png differ
diff --git a/MyFinance.Web/Content/bg-main-corner-sprite.png b/EFMVC.Web.API/Images/bullet.png
similarity index 65%
rename from MyFinance.Web/Content/bg-main-corner-sprite.png
rename to EFMVC.Web.API/Images/bullet.png
index 0c7921e..d3824c1 100644
Binary files a/MyFinance.Web/Content/bg-main-corner-sprite.png and b/EFMVC.Web.API/Images/bullet.png differ
diff --git a/EFMVC.Web.API/Images/heroAccent.png b/EFMVC.Web.API/Images/heroAccent.png
new file mode 100644
index 0000000..14ea59b
Binary files /dev/null and b/EFMVC.Web.API/Images/heroAccent.png differ
diff --git a/EFMVC.Web.API/Images/orderedList0.png b/EFMVC.Web.API/Images/orderedList0.png
new file mode 100644
index 0000000..7a4ea25
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList0.png differ
diff --git a/EFMVC.Web.API/Images/orderedList1.png b/EFMVC.Web.API/Images/orderedList1.png
new file mode 100644
index 0000000..523c24d
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList1.png differ
diff --git a/EFMVC.Web.API/Images/orderedList2.png b/EFMVC.Web.API/Images/orderedList2.png
new file mode 100644
index 0000000..553a2da
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList2.png differ
diff --git a/EFMVC.Web.API/Images/orderedList3.png b/EFMVC.Web.API/Images/orderedList3.png
new file mode 100644
index 0000000..0714981
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList3.png differ
diff --git a/EFMVC.Web.API/Images/orderedList4.png b/EFMVC.Web.API/Images/orderedList4.png
new file mode 100644
index 0000000..ce91e8f
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList4.png differ
diff --git a/EFMVC.Web.API/Images/orderedList5.png b/EFMVC.Web.API/Images/orderedList5.png
new file mode 100644
index 0000000..c073485
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList5.png differ
diff --git a/EFMVC.Web.API/Images/orderedList6.png b/EFMVC.Web.API/Images/orderedList6.png
new file mode 100644
index 0000000..3b9aa05
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList6.png differ
diff --git a/EFMVC.Web.API/Images/orderedList7.png b/EFMVC.Web.API/Images/orderedList7.png
new file mode 100644
index 0000000..f99c609
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList7.png differ
diff --git a/EFMVC.Web.API/Images/orderedList8.png b/EFMVC.Web.API/Images/orderedList8.png
new file mode 100644
index 0000000..127596d
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList8.png differ
diff --git a/EFMVC.Web.API/Images/orderedList9.png b/EFMVC.Web.API/Images/orderedList9.png
new file mode 100644
index 0000000..39cfdcf
Binary files /dev/null and b/EFMVC.Web.API/Images/orderedList9.png differ
diff --git a/EFMVC.Web.API/Models/CategoryModel.cs b/EFMVC.Web.API/Models/CategoryModel.cs
new file mode 100644
index 0000000..7becf12
--- /dev/null
+++ b/EFMVC.Web.API/Models/CategoryModel.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.ComponentModel.DataAnnotations;
+
+namespace EFMVC.Web.API.Models
+{
+ public class CategoryModel
+ {
+ public int CategoryId { get; set; }
+ [Required]
+ public string CategoryName { get; set; }
+ public string Description { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MyFinance.Web/Properties/AssemblyInfo.cs b/EFMVC.Web.API/Properties/AssemblyInfo.cs
similarity index 85%
rename from MyFinance.Web/Properties/AssemblyInfo.cs
rename to EFMVC.Web.API/Properties/AssemblyInfo.cs
index fc290b0..26c41df 100644
--- a/MyFinance.Web/Properties/AssemblyInfo.cs
+++ b/EFMVC.Web.API/Properties/AssemblyInfo.cs
@@ -5,12 +5,12 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("MyFinance.Web")]
+[assembly: AssemblyTitle("EFMVC.Web.API")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("MyFinance.Web")]
-[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyProduct("EFMVC.Web.API")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -20,7 +20,7 @@
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("3e3c2473-a8a4-439b-bdbe-d69ff834f15a")]
+[assembly: Guid("4e352cd1-4c68-41d3-9da4-4ca041211000")]
// Version information for an assembly consists of the following four values:
//
diff --git a/EFMVC.Web.API/Scripts/_references.js b/EFMVC.Web.API/Scripts/_references.js
new file mode 100644
index 0000000..e0c8a85
Binary files /dev/null and b/EFMVC.Web.API/Scripts/_references.js differ
diff --git a/EFMVC.Web.API/Scripts/jquery-1.8.2.intellisense.js b/EFMVC.Web.API/Scripts/jquery-1.8.2.intellisense.js
new file mode 100644
index 0000000..5514196
--- /dev/null
+++ b/EFMVC.Web.API/Scripts/jquery-1.8.2.intellisense.js
@@ -0,0 +1,2494 @@
+intellisense.annotate(jQuery, {
+ 'ajax': function() {
+ ///
+ /// Perform an asynchronous HTTP (Ajax) request.
+ /// A string containing the URL to which the request is sent.
+ /// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup(). See jQuery.ajax( settings ) below for a complete list of all settings.
+ ///
+ ///
+ ///
+ /// Perform an asynchronous HTTP (Ajax) request.
+ /// A set of key/value pairs that configure the Ajax request. All settings are optional. A default can be set for any option with $.ajaxSetup().
+ ///
+ ///
+ },
+ 'ajaxPrefilter': function() {
+ ///
+ /// Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax().
+ /// An optional string containing one or more space-separated dataTypes
+ /// A handler to set default values for future Ajax requests.
+ ///
+ },
+ 'ajaxSetup': function() {
+ ///
+ /// Set default values for future Ajax requests.
+ /// A set of key/value pairs that configure the default Ajax request. All options are optional.
+ ///
+ },
+ 'boxModel': function() {
+ /// Deprecated in jQuery 1.3 (see jQuery.support). States if the current page, in the user's browser, is being rendered using the W3C CSS Box Model.
+ ///
+ },
+ 'browser': function() {
+ /// Contains flags for the useragent, read from navigator.userAgent. We recommend against using this property; please try to use feature detection instead (see jQuery.support). jQuery.browser may be moved to a plugin in a future release of jQuery.
+ ///
+ },
+ 'browser.version': function() {
+ /// The version number of the rendering engine for the user's browser.
+ ///
+ },
+ 'Callbacks': function() {
+ ///
+ /// A multi-purpose callbacks list object that provides a powerful way to manage callback lists.
+ /// An optional list of space-separated flags that change how the callback list behaves.
+ ///
+ },
+ 'contains': function() {
+ ///
+ /// Check to see if a DOM element is within another DOM element.
+ /// The DOM element that may contain the other element.
+ /// The DOM element that may be contained by the other element.
+ ///
+ ///
+ },
+ 'cssHooks': function() {
+ /// Hook directly into jQuery to override how particular CSS properties are retrieved or set, normalize CSS property naming, or create custom properties.
+ ///
+ },
+ 'data': function() {
+ ///
+ /// Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element.
+ /// The DOM element to query for the data.
+ /// Name of the data stored.
+ ///
+ ///
+ ///
+ /// Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element.
+ /// The DOM element to query for the data.
+ ///
+ ///
+ },
+ 'dequeue': function() {
+ ///
+ /// Execute the next function on the queue for the matched element.
+ /// A DOM element from which to remove and execute a queued function.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ ///
+ },
+ 'each': function() {
+ ///
+ /// A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties.
+ /// The object or array to iterate over.
+ /// The function that will be executed on every object.
+ ///
+ ///
+ },
+ 'error': function() {
+ ///
+ /// Takes a string and throws an exception containing it.
+ /// The message to send out.
+ ///
+ },
+ 'extend': function() {
+ ///
+ /// Merge the contents of two or more objects together into the first object.
+ /// An object that will receive the new properties if additional objects are passed in or that will extend the jQuery namespace if it is the sole argument.
+ /// An object containing additional properties to merge in.
+ /// Additional objects containing properties to merge in.
+ ///
+ ///
+ ///
+ /// Merge the contents of two or more objects together into the first object.
+ /// If true, the merge becomes recursive (aka. deep copy).
+ /// The object to extend. It will receive the new properties.
+ /// An object containing additional properties to merge in.
+ /// Additional objects containing properties to merge in.
+ ///
+ ///
+ },
+ 'get': function() {
+ ///
+ /// Load data from the server using a HTTP GET request.
+ /// A string containing the URL to which the request is sent.
+ /// A map or string that is sent to the server with the request.
+ /// A callback function that is executed if the request succeeds.
+ /// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html).
+ ///
+ ///
+ },
+ 'getJSON': function() {
+ ///
+ /// Load JSON-encoded data from the server using a GET HTTP request.
+ /// A string containing the URL to which the request is sent.
+ /// A map or string that is sent to the server with the request.
+ /// A callback function that is executed if the request succeeds.
+ ///
+ ///
+ },
+ 'getScript': function() {
+ ///
+ /// Load a JavaScript file from the server using a GET HTTP request, then execute it.
+ /// A string containing the URL to which the request is sent.
+ /// A callback function that is executed if the request succeeds.
+ ///
+ ///
+ },
+ 'globalEval': function() {
+ ///
+ /// Execute some JavaScript code globally.
+ /// The JavaScript code to execute.
+ ///
+ },
+ 'grep': function() {
+ ///
+ /// Finds the elements of an array which satisfy a filter function. The original array is not affected.
+ /// The array to search through.
+ /// The function to process each item against. The first argument to the function is the item, and the second argument is the index. The function should return a Boolean value. this will be the global window object.
+ /// If "invert" is false, or not provided, then the function returns an array consisting of all elements for which "callback" returns true. If "invert" is true, then the function returns an array consisting of all elements for which "callback" returns false.
+ ///
+ ///
+ },
+ 'hasData': function() {
+ ///
+ /// Determine whether an element has any jQuery data associated with it.
+ /// A DOM element to be checked for data.
+ ///
+ ///
+ },
+ 'holdReady': function() {
+ ///
+ /// Holds or releases the execution of jQuery's ready event.
+ /// Indicates whether the ready hold is being requested or released
+ ///
+ },
+ 'inArray': function() {
+ ///
+ /// Search for a specified value within an array and return its index (or -1 if not found).
+ /// The value to search for.
+ /// An array through which to search.
+ /// The index of the array at which to begin the search. The default is 0, which will search the whole array.
+ ///
+ ///
+ },
+ 'isArray': function() {
+ ///
+ /// Determine whether the argument is an array.
+ /// Object to test whether or not it is an array.
+ ///
+ ///
+ },
+ 'isEmptyObject': function() {
+ ///
+ /// Check to see if an object is empty (contains no properties).
+ /// The object that will be checked to see if it's empty.
+ ///
+ ///
+ },
+ 'isFunction': function() {
+ ///
+ /// Determine if the argument passed is a Javascript function object.
+ /// Object to test whether or not it is a function.
+ ///
+ ///
+ },
+ 'isNumeric': function() {
+ ///
+ /// Determines whether its argument is a number.
+ /// The value to be tested.
+ ///
+ ///
+ },
+ 'isPlainObject': function() {
+ ///
+ /// Check to see if an object is a plain object (created using "{}" or "new Object").
+ /// The object that will be checked to see if it's a plain object.
+ ///
+ ///
+ },
+ 'isWindow': function() {
+ ///
+ /// Determine whether the argument is a window.
+ /// Object to test whether or not it is a window.
+ ///
+ ///
+ },
+ 'isXMLDoc': function() {
+ ///
+ /// Check to see if a DOM node is within an XML document (or is an XML document).
+ /// The DOM node that will be checked to see if it's in an XML document.
+ ///
+ ///
+ },
+ 'makeArray': function() {
+ ///
+ /// Convert an array-like object into a true JavaScript array.
+ /// Any object to turn into a native Array.
+ ///
+ ///
+ },
+ 'map': function() {
+ ///
+ /// Translate all items in an array or object to new array of items.
+ /// The Array to translate.
+ /// The function to process each item against. The first argument to the function is the array item, the second argument is the index in array The function can return any value. Within the function, this refers to the global (window) object.
+ ///
+ ///
+ ///
+ /// Translate all items in an array or object to new array of items.
+ /// The Array or Object to translate.
+ /// The function to process each item against. The first argument to the function is the value; the second argument is the index or key of the array or object property. The function can return any value to add to the array. A returned array will be flattened into the resulting array. Within the function, this refers to the global (window) object.
+ ///
+ ///
+ },
+ 'merge': function() {
+ ///
+ /// Merge the contents of two arrays together into the first array.
+ /// The first array to merge, the elements of second added.
+ /// The second array to merge into the first, unaltered.
+ ///
+ ///
+ },
+ 'noConflict': function() {
+ ///
+ /// Relinquish jQuery's control of the $ variable.
+ /// A Boolean indicating whether to remove all jQuery variables from the global scope (including jQuery itself).
+ ///
+ ///
+ },
+ 'noop': function() {
+ /// An empty function.
+ ///
+ },
+ 'now': function() {
+ /// Return a number representing the current time.
+ ///
+ },
+ 'param': function() {
+ ///
+ /// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request.
+ /// An array or object to serialize.
+ ///
+ ///
+ ///
+ /// Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request.
+ /// An array or object to serialize.
+ /// A Boolean indicating whether to perform a traditional "shallow" serialization.
+ ///
+ ///
+ },
+ 'parseJSON': function() {
+ ///
+ /// Takes a well-formed JSON string and returns the resulting JavaScript object.
+ /// The JSON string to parse.
+ ///
+ ///
+ },
+ 'parseXML': function() {
+ ///
+ /// Parses a string into an XML document.
+ /// a well-formed XML string to be parsed
+ ///
+ ///
+ },
+ 'post': function() {
+ ///
+ /// Load data from the server using a HTTP POST request.
+ /// A string containing the URL to which the request is sent.
+ /// A map or string that is sent to the server with the request.
+ /// A callback function that is executed if the request succeeds.
+ /// The type of data expected from the server. Default: Intelligent Guess (xml, json, script, text, html).
+ ///
+ ///
+ },
+ 'proxy': function() {
+ ///
+ /// Takes a function and returns a new one that will always have a particular context.
+ /// The function whose context will be changed.
+ /// The object to which the context (this) of the function should be set.
+ ///
+ ///
+ ///
+ /// Takes a function and returns a new one that will always have a particular context.
+ /// The object to which the context of the function should be set.
+ /// The name of the function whose context will be changed (should be a property of the context object).
+ ///
+ ///
+ },
+ 'queue': function() {
+ ///
+ /// Manipulate the queue of functions to be executed on the matched element.
+ /// A DOM element where the array of queued functions is attached.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ /// An array of functions to replace the current queue contents.
+ ///
+ ///
+ ///
+ /// Manipulate the queue of functions to be executed on the matched element.
+ /// A DOM element on which to add a queued function.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ /// The new function to add to the queue.
+ ///
+ ///
+ },
+ 'removeData': function() {
+ ///
+ /// Remove a previously-stored piece of data.
+ /// A DOM element from which to remove data.
+ /// A string naming the piece of data to remove.
+ ///
+ ///
+ },
+ 'sub': function() {
+ /// Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object.
+ ///
+ },
+ 'support': function() {
+ /// A collection of properties that represent the presence of different browser features or bugs. Primarily intended for jQuery's internal use; specific properties may be removed when they are no longer needed internally to improve page startup performance.
+ ///
+ },
+ 'trim': function() {
+ ///
+ /// Remove the whitespace from the beginning and end of a string.
+ /// The string to trim.
+ ///
+ ///
+ },
+ 'type': function() {
+ ///
+ /// Determine the internal JavaScript [[Class]] of an object.
+ /// Object to get the internal JavaScript [[Class]] of.
+ ///
+ ///
+ },
+ 'unique': function() {
+ ///
+ /// Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers.
+ /// The Array of DOM elements.
+ ///
+ ///
+ },
+ 'when': function() {
+ ///
+ /// Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.
+ /// One or more Deferred objects, or plain JavaScript objects.
+ ///
+ ///
+ },
+});
+
+var _1228819969 = jQuery.Callbacks;
+jQuery.Callbacks = function(flags) {
+var _object = _1228819969(flags);
+intellisense.annotate(_object, {
+ 'add': function() {
+ ///
+ /// Add a callback or a collection of callbacks to a callback list.
+ /// A function, or array of functions, that are to be added to the callback list.
+ ///
+ },
+ 'disable': function() {
+ /// Disable a callback list from doing anything more.
+ },
+ 'empty': function() {
+ /// Remove all of the callbacks from a list.
+ },
+ 'fire': function() {
+ ///
+ /// Call all of the callbacks with the given arguments
+ /// The argument or list of arguments to pass back to the callback list.
+ ///
+ },
+ 'fired': function() {
+ /// Determine if the callbacks have already been called at least once.
+ ///
+ },
+ 'fireWith': function() {
+ ///
+ /// Call all callbacks in a list with the given context and arguments.
+ /// A reference to the context in which the callbacks in the list should be fired.
+ /// An argument, or array of arguments, to pass to the callbacks in the list.
+ ///
+ },
+ 'has': function() {
+ ///
+ /// Determine whether a supplied callback is in a list
+ /// The callback to search for.
+ ///
+ ///
+ },
+ 'lock': function() {
+ /// Lock a callback list in its current state.
+ },
+ 'locked': function() {
+ /// Determine if the callbacks list has been locked.
+ ///
+ },
+ 'remove': function() {
+ ///
+ /// Remove a callback or a collection of callbacks from a callback list.
+ /// A function, or array of functions, that are to be removed from the callback list.
+ ///
+ },
+});
+
+return _object;
+};
+intellisense.redirectDefinition(jQuery.Callbacks, _1228819969);
+
+var _731531622 = jQuery.Deferred;
+jQuery.Deferred = function(func) {
+var _object = _731531622(func);
+intellisense.annotate(_object, {
+ 'always': function() {
+ ///
+ /// Add handlers to be called when the Deferred object is either resolved or rejected.
+ /// A function, or array of functions, that is called when the Deferred is resolved or rejected.
+ /// Optional additional functions, or arrays of functions, that are called when the Deferred is resolved or rejected.
+ ///
+ ///
+ },
+ 'done': function() {
+ ///
+ /// Add handlers to be called when the Deferred object is resolved.
+ /// A function, or array of functions, that are called when the Deferred is resolved.
+ /// Optional additional functions, or arrays of functions, that are called when the Deferred is resolved.
+ ///
+ ///
+ },
+ 'fail': function() {
+ ///
+ /// Add handlers to be called when the Deferred object is rejected.
+ /// A function, or array of functions, that are called when the Deferred is rejected.
+ /// Optional additional functions, or arrays of functions, that are called when the Deferred is rejected.
+ ///
+ ///
+ },
+ 'isRejected': function() {
+ /// Determine whether a Deferred object has been rejected.
+ ///
+ },
+ 'isResolved': function() {
+ /// Determine whether a Deferred object has been resolved.
+ ///
+ },
+ 'notify': function() {
+ ///
+ /// Call the progressCallbacks on a Deferred object with the given args.
+ /// Optional arguments that are passed to the progressCallbacks.
+ ///
+ ///
+ },
+ 'notifyWith': function() {
+ ///
+ /// Call the progressCallbacks on a Deferred object with the given context and args.
+ /// Context passed to the progressCallbacks as the this object.
+ /// Optional arguments that are passed to the progressCallbacks.
+ ///
+ ///
+ },
+ 'pipe': function() {
+ ///
+ /// Utility method to filter and/or chain Deferreds.
+ /// An optional function that is called when the Deferred is resolved.
+ /// An optional function that is called when the Deferred is rejected.
+ ///
+ ///
+ ///
+ /// Utility method to filter and/or chain Deferreds.
+ /// An optional function that is called when the Deferred is resolved.
+ /// An optional function that is called when the Deferred is rejected.
+ /// An optional function that is called when progress notifications are sent to the Deferred.
+ ///
+ ///
+ },
+ 'progress': function() {
+ ///
+ /// Add handlers to be called when the Deferred object generates progress notifications.
+ /// A function, or array of functions, that is called when the Deferred generates progress notifications.
+ ///
+ ///
+ },
+ 'promise': function() {
+ ///
+ /// Return a Deferred's Promise object.
+ /// Object onto which the promise methods have to be attached
+ ///
+ ///
+ },
+ 'reject': function() {
+ ///
+ /// Reject a Deferred object and call any failCallbacks with the given args.
+ /// Optional arguments that are passed to the failCallbacks.
+ ///
+ ///
+ },
+ 'rejectWith': function() {
+ ///
+ /// Reject a Deferred object and call any failCallbacks with the given context and args.
+ /// Context passed to the failCallbacks as the this object.
+ /// An optional array of arguments that are passed to the failCallbacks.
+ ///
+ ///
+ },
+ 'resolve': function() {
+ ///
+ /// Resolve a Deferred object and call any doneCallbacks with the given args.
+ /// Optional arguments that are passed to the doneCallbacks.
+ ///
+ ///
+ },
+ 'resolveWith': function() {
+ ///
+ /// Resolve a Deferred object and call any doneCallbacks with the given context and args.
+ /// Context passed to the doneCallbacks as the this object.
+ /// An optional array of arguments that are passed to the doneCallbacks.
+ ///
+ ///
+ },
+ 'state': function() {
+ /// Determine the current state of a Deferred object.
+ ///
+ },
+ 'then': function() {
+ ///
+ /// Add handlers to be called when the Deferred object is resolved or rejected.
+ /// A function, or array of functions, called when the Deferred is resolved.
+ /// A function, or array of functions, called when the Deferred is rejected.
+ ///
+ ///
+ ///
+ /// Add handlers to be called when the Deferred object is resolved or rejected.
+ /// A function, or array of functions, called when the Deferred is resolved.
+ /// A function, or array of functions, called when the Deferred is rejected.
+ /// A function, or array of functions, called when the Deferred notifies progress.
+ ///
+ ///
+ },
+});
+
+return _object;
+};
+intellisense.redirectDefinition(jQuery.Callbacks, _731531622);
+
+intellisense.annotate(jQuery.Event.prototype, {
+ 'currentTarget': function() {
+ /// The current DOM element within the event bubbling phase.
+ ///
+ },
+ 'data': function() {
+ /// An optional data map passed to an event method when the current executing handler is bound.
+ },
+ 'delegateTarget': function() {
+ /// The element where the currently-called jQuery event handler was attached.
+ ///
+ },
+ 'isDefaultPrevented': function() {
+ /// Returns whether event.preventDefault() was ever called on this event object.
+ ///
+ },
+ 'isImmediatePropagationStopped': function() {
+ /// Returns whether event.stopImmediatePropagation() was ever called on this event object.
+ ///
+ },
+ 'isPropagationStopped': function() {
+ /// Returns whether event.stopPropagation() was ever called on this event object.
+ ///
+ },
+ 'namespace': function() {
+ /// The namespace specified when the event was triggered.
+ ///
+ },
+ 'pageX': function() {
+ /// The mouse position relative to the left edge of the document.
+ ///
+ },
+ 'pageY': function() {
+ /// The mouse position relative to the top edge of the document.
+ ///
+ },
+ 'preventDefault': function() {
+ /// If this method is called, the default action of the event will not be triggered.
+ },
+ 'relatedTarget': function() {
+ /// The other DOM element involved in the event, if any.
+ ///
+ },
+ 'result': function() {
+ /// The last value returned by an event handler that was triggered by this event, unless the value was undefined.
+ ///
+ },
+ 'stopImmediatePropagation': function() {
+ /// Keeps the rest of the handlers from being executed and prevents the event from bubbling up the DOM tree.
+ },
+ 'stopPropagation': function() {
+ /// Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
+ },
+ 'target': function() {
+ /// The DOM element that initiated the event.
+ ///
+ },
+ 'timeStamp': function() {
+ /// The difference in milliseconds between the time the browser created the event and January 1, 1970.
+ ///
+ },
+ 'type': function() {
+ /// Describes the nature of the event.
+ ///
+ },
+ 'which': function() {
+ /// For key or mouse events, this property indicates the specific key or button that was pressed.
+ ///
+ },
+});
+
+intellisense.annotate(jQuery.fn, {
+ 'add': function() {
+ ///
+ /// Add elements to the set of matched elements.
+ /// A string representing a selector expression to find additional elements to add to the set of matched elements.
+ ///
+ ///
+ ///
+ /// Add elements to the set of matched elements.
+ /// One or more elements to add to the set of matched elements.
+ ///
+ ///
+ ///
+ /// Add elements to the set of matched elements.
+ /// An HTML fragment to add to the set of matched elements.
+ ///
+ ///
+ ///
+ /// Add elements to the set of matched elements.
+ /// An existing jQuery object to add to the set of matched elements.
+ ///
+ ///
+ ///
+ /// Add elements to the set of matched elements.
+ /// A string representing a selector expression to find additional elements to add to the set of matched elements.
+ /// The point in the document at which the selector should begin matching; similar to the context argument of the $(selector, context) method.
+ ///
+ ///
+ },
+ 'addClass': function() {
+ ///
+ /// Adds the specified class(es) to each of the set of matched elements.
+ /// One or more class names to be added to the class attribute of each matched element.
+ ///
+ ///
+ ///
+ /// Adds the specified class(es) to each of the set of matched elements.
+ /// A function returning one or more space-separated class names to be added to the existing class name(s). Receives the index position of the element in the set and the existing class name(s) as arguments. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'after': function() {
+ ///
+ /// Insert content, specified by the parameter, after each element in the set of matched elements.
+ /// HTML string, DOM element, or jQuery object to insert after each element in the set of matched elements.
+ /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert after each element in the set of matched elements.
+ ///
+ ///
+ ///
+ /// Insert content, specified by the parameter, after each element in the set of matched elements.
+ /// A function that returns an HTML string, DOM element(s), or jQuery object to insert after each element in the set of matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'ajaxComplete': function() {
+ ///
+ /// Register a handler to be called when Ajax requests complete. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'ajaxError': function() {
+ ///
+ /// Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'ajaxSend': function() {
+ ///
+ /// Attach a function to be executed before an Ajax request is sent. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'ajaxStart': function() {
+ ///
+ /// Register a handler to be called when the first Ajax request begins. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'ajaxStop': function() {
+ ///
+ /// Register a handler to be called when all Ajax requests have completed. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'ajaxSuccess': function() {
+ ///
+ /// Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event.
+ /// The function to be invoked.
+ ///
+ ///
+ },
+ 'all': function() {
+ /// Selects all elements.
+ },
+ 'andSelf': function() {
+ /// Add the previous set of elements on the stack to the current set.
+ ///
+ },
+ 'animate': function() {
+ ///
+ /// Perform a custom animation of a set of CSS properties.
+ /// A map of CSS properties that the animation will move toward.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Perform a custom animation of a set of CSS properties.
+ /// A map of CSS properties that the animation will move toward.
+ /// A map of additional options to pass to the method. Supported keys: duration: A string or number determining how long the animation will run.easing: A string indicating which easing function to use for the transition.complete: A function to call once the animation is complete.step: A function to be called after each step of the animation.queue: A Boolean indicating whether to place the animation in the effects queue. If false, the animation will begin immediately. As of jQuery 1.7, the queue option can also accept a string, in which case the animation is added to the queue represented by that string.specialEasing: A map of one or more of the CSS properties defined by the properties argument and their corresponding easing functions (added 1.4).
+ ///
+ ///
+ },
+ 'animated': function() {
+ /// Select all elements that are in the progress of an animation at the time the selector is run.
+ },
+ 'append': function() {
+ ///
+ /// Insert content, specified by the parameter, to the end of each element in the set of matched elements.
+ /// DOM element, HTML string, or jQuery object to insert at the end of each element in the set of matched elements.
+ /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements.
+ ///
+ ///
+ ///
+ /// Insert content, specified by the parameter, to the end of each element in the set of matched elements.
+ /// A function that returns an HTML string, DOM element(s), or jQuery object to insert at the end of each element in the set of matched elements. Receives the index position of the element in the set and the old HTML value of the element as arguments. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'appendTo': function() {
+ ///
+ /// Insert every element in the set of matched elements to the end of the target.
+ /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the end of the element(s) specified by this parameter.
+ ///
+ ///
+ },
+ 'attr': function() {
+ ///
+ /// Set one or more attributes for the set of matched elements.
+ /// The name of the attribute to set.
+ /// A value to set for the attribute.
+ ///
+ ///
+ ///
+ /// Set one or more attributes for the set of matched elements.
+ /// A map of attribute-value pairs to set.
+ ///
+ ///
+ ///
+ /// Set one or more attributes for the set of matched elements.
+ /// The name of the attribute to set.
+ /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old attribute value as arguments.
+ ///
+ ///
+ },
+ 'attributeContains': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value containing the a given substring.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeContainsPrefix': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value either equal to a given string or starting with that string followed by a hyphen (-).
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeContainsWord': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value containing a given word, delimited by spaces.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeEndsWith': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value ending exactly with a given string. The comparison is case sensitive.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeEquals': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value exactly equal to a certain value.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeHas': function() {
+ ///
+ /// Selects elements that have the specified attribute, with any value.
+ /// An attribute name.
+ ///
+ },
+ 'attributeMultiple': function() {
+ ///
+ /// Matches elements that match all of the specified attribute filters.
+ /// An attribute filter.
+ /// Another attribute filter, reducing the selection even more
+ /// As many more attribute filters as necessary
+ ///
+ },
+ 'attributeNotEqual': function() {
+ ///
+ /// Select elements that either don't have the specified attribute, or do have the specified attribute but not with a certain value.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'attributeStartsWith': function() {
+ ///
+ /// Selects elements that have the specified attribute with a value beginning exactly with a given string.
+ /// An attribute name.
+ /// An attribute value. Can be either an unquoted single word or a quoted string.
+ ///
+ },
+ 'before': function() {
+ ///
+ /// Insert content, specified by the parameter, before each element in the set of matched elements.
+ /// HTML string, DOM element, or jQuery object to insert before each element in the set of matched elements.
+ /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert before each element in the set of matched elements.
+ ///
+ ///
+ ///
+ /// Insert content, specified by the parameter, before each element in the set of matched elements.
+ /// A function that returns an HTML string, DOM element(s), or jQuery object to insert before each element in the set of matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'bind': function() {
+ ///
+ /// Attach a handler to an event for the elements.
+ /// A string containing one or more DOM event types, such as "click" or "submit," or custom event names.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach a handler to an event for the elements.
+ /// A string containing one or more DOM event types, such as "click" or "submit," or custom event names.
+ /// A map of data that will be passed to the event handler.
+ /// Setting the third argument to false will attach a function that prevents the default action from occurring and stops the event from bubbling. The default is true.
+ ///
+ ///
+ ///
+ /// Attach a handler to an event for the elements.
+ /// A map of one or more DOM event types and functions to execute for them.
+ ///
+ ///
+ },
+ 'blur': function() {
+ ///
+ /// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "blur" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'button': function() {
+ /// Selects all button elements and elements of type button.
+ },
+ 'change': function() {
+ ///
+ /// Bind an event handler to the "change" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "change" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'checkbox': function() {
+ /// Selects all elements of type checkbox.
+ },
+ 'checked': function() {
+ /// Matches all elements that are checked.
+ },
+ 'child': function() {
+ ///
+ /// Selects all direct child elements specified by "child" of elements specified by "parent".
+ /// Any valid selector.
+ /// A selector to filter the child elements.
+ ///
+ },
+ 'children': function() {
+ ///
+ /// Get the children of each element in the set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'class': function() {
+ ///
+ /// Selects all elements with the given class.
+ /// A class to search for. An element can have multiple classes; only one of them must match.
+ ///
+ },
+ 'clearQueue': function() {
+ ///
+ /// Remove from the queue all items that have not yet been run.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ ///
+ ///
+ },
+ 'click': function() {
+ ///
+ /// Bind an event handler to the "click" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "click" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'clone': function() {
+ ///
+ /// Create a deep copy of the set of matched elements.
+ /// A Boolean indicating whether event handlers should be copied along with the elements. As of jQuery 1.4, element data will be copied as well.
+ ///
+ ///
+ ///
+ /// Create a deep copy of the set of matched elements.
+ /// A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false. *In jQuery 1.5.0 the default value was incorrectly true; it was changed back to false in 1.5.1 and up.
+ /// A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false).
+ ///
+ ///
+ },
+ 'closest': function() {
+ ///
+ /// Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.
+ /// A string containing a selector expression to match elements against.
+ /// A DOM element within which a matching element may be found. If no context is passed in then the context of the jQuery set will be used instead.
+ ///
+ ///
+ ///
+ /// Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.
+ /// A jQuery object to match elements against.
+ ///
+ ///
+ ///
+ /// Get the first element that matches the selector, beginning at the current element and progressing up through the DOM tree.
+ /// An element to match elements against.
+ ///
+ ///
+ },
+ 'contains': function() {
+ ///
+ /// Select all elements that contain the specified text.
+ /// A string of text to look for. It's case sensitive.
+ ///
+ },
+ 'contents': function() {
+ /// Get the children of each element in the set of matched elements, including text and comment nodes.
+ ///
+ },
+ 'context': function() {
+ /// The DOM node context originally passed to jQuery(); if none was passed then context will likely be the document.
+ ///
+ },
+ 'css': function() {
+ ///
+ /// Set one or more CSS properties for the set of matched elements.
+ /// A CSS property name.
+ /// A value to set for the property.
+ ///
+ ///
+ ///
+ /// Set one or more CSS properties for the set of matched elements.
+ /// A CSS property name.
+ /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old value as arguments.
+ ///
+ ///
+ ///
+ /// Set one or more CSS properties for the set of matched elements.
+ /// A map of property-value pairs to set.
+ ///
+ ///
+ },
+ 'data': function() {
+ ///
+ /// Store arbitrary data associated with the matched elements.
+ /// A string naming the piece of data to set.
+ /// The new data value; it can be any Javascript type including Array or Object.
+ ///
+ ///
+ ///
+ /// Store arbitrary data associated with the matched elements.
+ /// An object of key-value pairs of data to update.
+ ///
+ ///
+ },
+ 'dblclick': function() {
+ ///
+ /// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'delay': function() {
+ ///
+ /// Set a timer to delay execution of subsequent items in the queue.
+ /// An integer indicating the number of milliseconds to delay execution of the next item in the queue.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ ///
+ ///
+ },
+ 'delegate': function() {
+ ///
+ /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
+ /// A selector to filter the elements that trigger the event.
+ /// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names.
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
+ /// A selector to filter the elements that trigger the event.
+ /// A string containing one or more space-separated JavaScript event types, such as "click" or "keydown," or custom event names.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
+ /// A selector to filter the elements that trigger the event.
+ /// A map of one or more event types and functions to execute for them.
+ ///
+ ///
+ },
+ 'dequeue': function() {
+ ///
+ /// Execute the next function on the queue for the matched elements.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ ///
+ ///
+ },
+ 'descendant': function() {
+ ///
+ /// Selects all elements that are descendants of a given ancestor.
+ /// Any valid selector.
+ /// A selector to filter the descendant elements.
+ ///
+ },
+ 'detach': function() {
+ ///
+ /// Remove the set of matched elements from the DOM.
+ /// A selector expression that filters the set of matched elements to be removed.
+ ///
+ ///
+ },
+ 'die': function() {
+ ///
+ /// Remove an event handler previously attached using .live() from the elements.
+ /// A string containing a JavaScript event type, such as click or keydown.
+ /// The function that is no longer to be executed.
+ ///
+ ///
+ ///
+ /// Remove an event handler previously attached using .live() from the elements.
+ /// A map of one or more event types, such as click or keydown and their corresponding functions that are no longer to be executed.
+ ///
+ ///
+ },
+ 'disabled': function() {
+ /// Selects all elements that are disabled.
+ },
+ 'each': function() {
+ ///
+ /// Iterate over a jQuery object, executing a function for each matched element.
+ /// A function to execute for each matched element.
+ ///
+ ///
+ },
+ 'element': function() {
+ ///
+ /// Selects all elements with the given tag name.
+ /// An element to search for. Refers to the tagName of DOM nodes.
+ ///
+ },
+ 'empty': function() {
+ /// Select all elements that have no children (including text nodes).
+ },
+ 'enabled': function() {
+ /// Selects all elements that are enabled.
+ },
+ 'end': function() {
+ /// End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
+ ///
+ },
+ 'eq': function() {
+ ///
+ /// Reduce the set of matched elements to the one at the specified index.
+ /// An integer indicating the 0-based position of the element.
+ ///
+ ///
+ ///
+ /// Reduce the set of matched elements to the one at the specified index.
+ /// An integer indicating the position of the element, counting backwards from the last element in the set.
+ ///
+ ///
+ },
+ 'error': function() {
+ ///
+ /// Bind an event handler to the "error" JavaScript event.
+ /// A function to execute when the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "error" JavaScript event.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'even': function() {
+ /// Selects even elements, zero-indexed. See also odd.
+ },
+ 'fadeIn': function() {
+ ///
+ /// Display the matched elements by fading them to opaque.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display the matched elements by fading them to opaque.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'fadeOut': function() {
+ ///
+ /// Hide the matched elements by fading them to transparent.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Hide the matched elements by fading them to transparent.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'fadeTo': function() {
+ ///
+ /// Adjust the opacity of the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A number between 0 and 1 denoting the target opacity.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Adjust the opacity of the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A number between 0 and 1 denoting the target opacity.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'fadeToggle': function() {
+ ///
+ /// Display or hide the matched elements by animating their opacity.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'file': function() {
+ /// Selects all elements of type file.
+ },
+ 'filter': function() {
+ ///
+ /// Reduce the set of matched elements to those that match the selector or pass the function's test.
+ /// A string containing a selector expression to match the current set of elements against.
+ ///
+ ///
+ ///
+ /// Reduce the set of matched elements to those that match the selector or pass the function's test.
+ /// A function used as a test for each element in the set. this is the current DOM element.
+ ///
+ ///
+ ///
+ /// Reduce the set of matched elements to those that match the selector or pass the function's test.
+ /// An element to match the current set of elements against.
+ ///
+ ///
+ ///
+ /// Reduce the set of matched elements to those that match the selector or pass the function's test.
+ /// An existing jQuery object to match the current set of elements against.
+ ///
+ ///
+ },
+ 'find': function() {
+ ///
+ /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
+ /// A jQuery object to match elements against.
+ ///
+ ///
+ ///
+ /// Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
+ /// An element to match elements against.
+ ///
+ ///
+ },
+ 'first': function() {
+ /// Selects the first matched element.
+ },
+ 'first-child': function() {
+ /// Selects all elements that are the first child of their parent.
+ },
+ 'focus': function() {
+ ///
+ /// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "focus" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'focusin': function() {
+ ///
+ /// Bind an event handler to the "focusin" event.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "focusin" event.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'focusout': function() {
+ ///
+ /// Bind an event handler to the "focusout" JavaScript event.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "focusout" JavaScript event.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'get': function() {
+ ///
+ /// Retrieve the DOM elements matched by the jQuery object.
+ /// A zero-based integer indicating which element to retrieve.
+ ///
+ ///
+ },
+ 'gt': function() {
+ ///
+ /// Select all elements at an index greater than index within the matched set.
+ /// Zero-based index.
+ ///
+ },
+ 'has': function() {
+ ///
+ /// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.
+ /// A DOM element to match elements against.
+ ///
+ ///
+ },
+ 'hasClass': function() {
+ ///
+ /// Determine whether any of the matched elements are assigned the given class.
+ /// The class name to search for.
+ ///
+ ///
+ },
+ 'header': function() {
+ /// Selects all elements that are headers, like h1, h2, h3 and so on.
+ },
+ 'height': function() {
+ ///
+ /// Set the CSS height of every matched element.
+ /// An integer representing the number of pixels, or an integer with an optional unit of measure appended (as a string).
+ ///
+ ///
+ ///
+ /// Set the CSS height of every matched element.
+ /// A function returning the height to set. Receives the index position of the element in the set and the old height as arguments. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'hidden': function() {
+ /// Selects all elements that are hidden.
+ },
+ 'hide': function() {
+ ///
+ /// Hide the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Hide the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'hover': function() {
+ ///
+ /// Bind two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements.
+ /// A function to execute when the mouse pointer enters the element.
+ /// A function to execute when the mouse pointer leaves the element.
+ ///
+ ///
+ },
+ 'html': function() {
+ ///
+ /// Set the HTML contents of each element in the set of matched elements.
+ /// A string of HTML to set as the content of each matched element.
+ ///
+ ///
+ ///
+ /// Set the HTML contents of each element in the set of matched elements.
+ /// A function returning the HTML content to set. Receives the index position of the element in the set and the old HTML value as arguments. jQuery empties the element before calling the function; use the oldhtml argument to reference the previous content. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'id': function() {
+ ///
+ /// Selects a single element with the given id attribute.
+ /// An ID to search for, specified via the id attribute of an element.
+ ///
+ },
+ 'image': function() {
+ /// Selects all elements of type image.
+ },
+ 'index': function() {
+ ///
+ /// Search for a given element from among the matched elements.
+ /// A selector representing a jQuery collection in which to look for an element.
+ ///
+ ///
+ ///
+ /// Search for a given element from among the matched elements.
+ /// The DOM element or first element within the jQuery object to look for.
+ ///
+ ///
+ },
+ 'init': function() {
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A string containing a selector expression
+ /// A DOM Element, Document, or jQuery to use as context
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A DOM element to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A plain object to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// An array containing a set of DOM elements to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// An existing jQuery object to clone.
+ ///
+ ///
+ },
+ 'innerHeight': function() {
+ /// Get the current computed height for the first element in the set of matched elements, including padding but not border.
+ ///
+ },
+ 'innerWidth': function() {
+ /// Get the current computed width for the first element in the set of matched elements, including padding but not border.
+ ///
+ },
+ 'input': function() {
+ /// Selects all input, textarea, select and button elements.
+ },
+ 'insertAfter': function() {
+ ///
+ /// Insert every element in the set of matched elements after the target.
+ /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted after the element(s) specified by this parameter.
+ ///
+ ///
+ },
+ 'insertBefore': function() {
+ ///
+ /// Insert every element in the set of matched elements before the target.
+ /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted before the element(s) specified by this parameter.
+ ///
+ ///
+ },
+ 'is': function() {
+ ///
+ /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
+ /// A function used as a test for the set of elements. It accepts one argument, index, which is the element's index in the jQuery collection.Within the function, this refers to the current DOM element.
+ ///
+ ///
+ ///
+ /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
+ /// An existing jQuery object to match the current set of elements against.
+ ///
+ ///
+ ///
+ /// Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
+ /// An element to match the current set of elements against.
+ ///
+ ///
+ },
+ 'jquery': function() {
+ /// A string containing the jQuery version number.
+ ///
+ },
+ 'keydown': function() {
+ ///
+ /// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'keypress': function() {
+ ///
+ /// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'keyup': function() {
+ ///
+ /// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'last': function() {
+ /// Selects the last matched element.
+ },
+ 'last-child': function() {
+ /// Selects all elements that are the last child of their parent.
+ },
+ 'length': function() {
+ /// The number of elements in the jQuery object.
+ ///
+ },
+ 'live': function() {
+ ///
+ /// Attach an event handler for all elements which match the current selector, now and in the future.
+ /// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names.
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach an event handler for all elements which match the current selector, now and in the future.
+ /// A string containing a JavaScript event type, such as "click" or "keydown." As of jQuery 1.4 the string can contain multiple, space-separated event types or custom event names.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach an event handler for all elements which match the current selector, now and in the future.
+ /// A map of one or more JavaScript event types and functions to execute for them.
+ ///
+ ///
+ },
+ 'load': function() {
+ ///
+ /// Bind an event handler to the "load" JavaScript event.
+ /// A function to execute when the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "load" JavaScript event.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'lt': function() {
+ ///
+ /// Select all elements at an index less than index within the matched set.
+ /// Zero-based index.
+ ///
+ },
+ 'map': function() {
+ ///
+ /// Pass each element in the current matched set through a function, producing a new jQuery object containing the return values.
+ /// A function object that will be invoked for each element in the current set.
+ ///
+ ///
+ },
+ 'mousedown': function() {
+ ///
+ /// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mouseenter': function() {
+ ///
+ /// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mouseleave': function() {
+ ///
+ /// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mousemove': function() {
+ ///
+ /// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mouseout': function() {
+ ///
+ /// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mouseover': function() {
+ ///
+ /// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'mouseup': function() {
+ ///
+ /// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'multiple': function() {
+ ///
+ /// Selects the combined results of all the specified selectors.
+ /// Any valid selector.
+ /// Another valid selector.
+ /// As many more valid selectors as you like.
+ ///
+ },
+ 'next': function() {
+ ///
+ /// Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'next adjacent': function() {
+ ///
+ /// Selects all next elements matching "next" that are immediately preceded by a sibling "prev".
+ /// Any valid selector.
+ /// A selector to match the element that is next to the first selector.
+ ///
+ },
+ 'next siblings': function() {
+ ///
+ /// Selects all sibling elements that follow after the "prev" element, have the same parent, and match the filtering "siblings" selector.
+ /// Any valid selector.
+ /// A selector to filter elements that are the following siblings of the first selector.
+ ///
+ },
+ 'nextAll': function() {
+ ///
+ /// Get all following siblings of each element in the set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'nextUntil': function() {
+ ///
+ /// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed.
+ /// A string containing a selector expression to indicate where to stop matching following sibling elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed.
+ /// A DOM node or jQuery object indicating where to stop matching following sibling elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'not': function() {
+ ///
+ /// Remove elements from the set of matched elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Remove elements from the set of matched elements.
+ /// One or more DOM elements to remove from the matched set.
+ ///
+ ///
+ ///
+ /// Remove elements from the set of matched elements.
+ /// A function used as a test for each element in the set. this is the current DOM element.
+ ///
+ ///
+ ///
+ /// Remove elements from the set of matched elements.
+ /// An existing jQuery object to match the current set of elements against.
+ ///
+ ///
+ },
+ 'nth-child': function() {
+ ///
+ /// Selects all elements that are the nth-child of their parent.
+ /// The index of each child to match, starting with 1, the string even or odd, or an equation ( eg. :nth-child(even), :nth-child(4n) )
+ ///
+ },
+ 'odd': function() {
+ /// Selects odd elements, zero-indexed. See also even.
+ },
+ 'off': function() {
+ ///
+ /// Remove an event handler.
+ /// One or more space-separated event types and optional namespaces, or just namespaces, such as "click", "keydown.myPlugin", or ".myPlugin".
+ /// A selector which should match the one originally passed to .on() when attaching event handlers.
+ /// A handler function previously attached for the event(s), or the special value false.
+ ///
+ ///
+ ///
+ /// Remove an event handler.
+ /// A map where the string keys represent one or more space-separated event types and optional namespaces, and the values represent handler functions previously attached for the event(s).
+ /// A selector which should match the one originally passed to .on() when attaching event handlers.
+ ///
+ ///
+ },
+ 'offset': function() {
+ ///
+ /// Set the current coordinates of every element in the set of matched elements, relative to the document.
+ /// An object containing the properties top and left, which are integers indicating the new top and left coordinates for the elements.
+ ///
+ ///
+ ///
+ /// Set the current coordinates of every element in the set of matched elements, relative to the document.
+ /// A function to return the coordinates to set. Receives the index of the element in the collection as the first argument and the current coordinates as the second argument. The function should return an object with the new top and left properties.
+ ///
+ ///
+ },
+ 'offsetParent': function() {
+ /// Get the closest ancestor element that is positioned.
+ ///
+ },
+ 'on': function() {
+ ///
+ /// Attach an event handler function for one or more events to the selected elements.
+ /// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin".
+ /// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element.
+ /// Data to be passed to the handler in event.data when an event is triggered.
+ /// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false.
+ ///
+ ///
+ ///
+ /// Attach an event handler function for one or more events to the selected elements.
+ /// A map in which the string keys represent one or more space-separated event types and optional namespaces, and the values represent a handler function to be called for the event(s).
+ /// A selector string to filter the descendants of the selected elements that will call the handler. If the selector is null or omitted, the handler is always called when it reaches the selected element.
+ /// Data to be passed to the handler in event.data when an event occurs.
+ ///
+ ///
+ },
+ 'one': function() {
+ ///
+ /// Attach a handler to an event for the elements. The handler is executed at most once per element.
+ /// A string containing one or more JavaScript event types, such as "click" or "submit," or custom event names.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Attach a handler to an event for the elements. The handler is executed at most once per element.
+ /// One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin".
+ /// A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element.
+ /// Data to be passed to the handler in event.data when an event is triggered.
+ /// A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false.
+ ///
+ ///
+ ///
+ /// Attach a handler to an event for the elements. The handler is executed at most once per element.
+ /// A map in which the string keys represent one or more space-separated event types and optional namespaces, and the values represent a handler function to be called for the event(s).
+ /// A selector string to filter the descendants of the selected elements that will call the handler. If the selector is null or omitted, the handler is always called when it reaches the selected element.
+ /// Data to be passed to the handler in event.data when an event occurs.
+ ///
+ ///
+ },
+ 'only-child': function() {
+ /// Selects all elements that are the only child of their parent.
+ },
+ 'outerHeight': function() {
+ ///
+ /// Get the current computed height for the first element in the set of matched elements, including padding, border, and optionally margin. Returns an integer (without "px") representation of the value or null if called on an empty set of elements.
+ /// A Boolean indicating whether to include the element's margin in the calculation.
+ ///
+ ///
+ },
+ 'outerWidth': function() {
+ ///
+ /// Get the current computed width for the first element in the set of matched elements, including padding and border.
+ /// A Boolean indicating whether to include the element's margin in the calculation.
+ ///
+ ///
+ },
+ 'parent': function() {
+ ///
+ /// Get the parent of each element in the current set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'parents': function() {
+ ///
+ /// Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'parentsUntil': function() {
+ ///
+ /// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.
+ /// A string containing a selector expression to indicate where to stop matching ancestor elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.
+ /// A DOM node or jQuery object indicating where to stop matching ancestor elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'password': function() {
+ /// Selects all elements of type password.
+ },
+ 'position': function() {
+ /// Get the current coordinates of the first element in the set of matched elements, relative to the offset parent.
+ ///
+ },
+ 'prepend': function() {
+ ///
+ /// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements.
+ /// DOM element, array of elements, HTML string, or jQuery object to insert at the beginning of each element in the set of matched elements.
+ /// One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the beginning of each element in the set of matched elements.
+ ///
+ ///
+ ///
+ /// Insert content, specified by the parameter, to the beginning of each element in the set of matched elements.
+ /// A function that returns an HTML string, DOM element(s), or jQuery object to insert at the beginning of each element in the set of matched elements. Receives the index position of the element in the set and the old HTML value of the element as arguments. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'prependTo': function() {
+ ///
+ /// Insert every element in the set of matched elements to the beginning of the target.
+ /// A selector, element, HTML string, or jQuery object; the matched set of elements will be inserted at the beginning of the element(s) specified by this parameter.
+ ///
+ ///
+ },
+ 'prev': function() {
+ ///
+ /// Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'prevAll': function() {
+ ///
+ /// Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'prevUntil': function() {
+ ///
+ /// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object.
+ /// A string containing a selector expression to indicate where to stop matching preceding sibling elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ ///
+ /// Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object.
+ /// A DOM node or jQuery object indicating where to stop matching preceding sibling elements.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'promise': function() {
+ ///
+ /// Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished.
+ /// The type of queue that needs to be observed.
+ /// Object onto which the promise methods have to be attached
+ ///
+ ///
+ },
+ 'prop': function() {
+ ///
+ /// Set one or more properties for the set of matched elements.
+ /// The name of the property to set.
+ /// A value to set for the property.
+ ///
+ ///
+ ///
+ /// Set one or more properties for the set of matched elements.
+ /// A map of property-value pairs to set.
+ ///
+ ///
+ ///
+ /// Set one or more properties for the set of matched elements.
+ /// The name of the property to set.
+ /// A function returning the value to set. Receives the index position of the element in the set and the old property value as arguments. Within the function, the keyword this refers to the current element.
+ ///
+ ///
+ },
+ 'pushStack': function() {
+ ///
+ /// Add a collection of DOM elements onto the jQuery stack.
+ /// An array of elements to push onto the stack and make into a new jQuery object.
+ ///
+ ///
+ ///
+ /// Add a collection of DOM elements onto the jQuery stack.
+ /// An array of elements to push onto the stack and make into a new jQuery object.
+ /// The name of a jQuery method that generated the array of elements.
+ /// The arguments that were passed in to the jQuery method (for serialization).
+ ///
+ ///
+ },
+ 'queue': function() {
+ ///
+ /// Manipulate the queue of functions to be executed on the matched elements.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ /// An array of functions to replace the current queue contents.
+ ///
+ ///
+ ///
+ /// Manipulate the queue of functions to be executed on the matched elements.
+ /// A string containing the name of the queue. Defaults to fx, the standard effects queue.
+ /// The new function to add to the queue, with a function to call that will dequeue the next item.
+ ///
+ ///
+ },
+ 'radio': function() {
+ /// Selects all elements of type radio.
+ },
+ 'ready': function() {
+ ///
+ /// Specify a function to execute when the DOM is fully loaded.
+ /// A function to execute after the DOM is ready.
+ ///
+ ///
+ },
+ 'remove': function() {
+ ///
+ /// Remove the set of matched elements from the DOM.
+ /// A selector expression that filters the set of matched elements to be removed.
+ ///
+ ///
+ },
+ 'removeAttr': function() {
+ ///
+ /// Remove an attribute from each element in the set of matched elements.
+ /// An attribute to remove; as of version 1.7, it can be a space-separated list of attributes.
+ ///
+ ///
+ },
+ 'removeClass': function() {
+ ///
+ /// Remove a single class, multiple classes, or all classes from each element in the set of matched elements.
+ /// One or more space-separated classes to be removed from the class attribute of each matched element.
+ ///
+ ///
+ ///
+ /// Remove a single class, multiple classes, or all classes from each element in the set of matched elements.
+ /// A function returning one or more space-separated class names to be removed. Receives the index position of the element in the set and the old class value as arguments.
+ ///
+ ///
+ },
+ 'removeData': function() {
+ ///
+ /// Remove a previously-stored piece of data.
+ /// A string naming the piece of data to delete.
+ ///
+ ///
+ ///
+ /// Remove a previously-stored piece of data.
+ /// An array or space-separated string naming the pieces of data to delete.
+ ///
+ ///
+ },
+ 'removeProp': function() {
+ ///
+ /// Remove a property for the set of matched elements.
+ /// The name of the property to set.
+ ///
+ ///
+ },
+ 'replaceAll': function() {
+ ///
+ /// Replace each target element with the set of matched elements.
+ /// A selector expression indicating which element(s) to replace.
+ ///
+ ///
+ },
+ 'replaceWith': function() {
+ ///
+ /// Replace each element in the set of matched elements with the provided new content.
+ /// The content to insert. May be an HTML string, DOM element, or jQuery object.
+ ///
+ ///
+ ///
+ /// Replace each element in the set of matched elements with the provided new content.
+ /// A function that returns content with which to replace the set of matched elements.
+ ///
+ ///
+ },
+ 'reset': function() {
+ /// Selects all elements of type reset.
+ },
+ 'resize': function() {
+ ///
+ /// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "resize" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'scroll': function() {
+ ///
+ /// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'scrollLeft': function() {
+ ///
+ /// Set the current horizontal position of the scroll bar for each of the set of matched elements.
+ /// An integer indicating the new position to set the scroll bar to.
+ ///
+ ///
+ },
+ 'scrollTop': function() {
+ ///
+ /// Set the current vertical position of the scroll bar for each of the set of matched elements.
+ /// An integer indicating the new position to set the scroll bar to.
+ ///
+ ///
+ },
+ 'select': function() {
+ ///
+ /// Bind an event handler to the "select" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "select" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'selected': function() {
+ /// Selects all elements that are selected.
+ },
+ 'serialize': function() {
+ /// Encode a set of form elements as a string for submission.
+ ///
+ },
+ 'serializeArray': function() {
+ /// Encode a set of form elements as an array of names and values.
+ ///
+ },
+ 'show': function() {
+ ///
+ /// Display the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'siblings': function() {
+ ///
+ /// Get the siblings of each element in the set of matched elements, optionally filtered by a selector.
+ /// A string containing a selector expression to match elements against.
+ ///
+ ///
+ },
+ 'size': function() {
+ /// Return the number of elements in the jQuery object.
+ ///
+ },
+ 'slice': function() {
+ ///
+ /// Reduce the set of matched elements to a subset specified by a range of indices.
+ /// An integer indicating the 0-based position at which the elements begin to be selected. If negative, it indicates an offset from the end of the set.
+ /// An integer indicating the 0-based position at which the elements stop being selected. If negative, it indicates an offset from the end of the set. If omitted, the range continues until the end of the set.
+ ///
+ ///
+ },
+ 'slideDown': function() {
+ ///
+ /// Display the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'slideToggle': function() {
+ ///
+ /// Display or hide the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display or hide the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'slideUp': function() {
+ ///
+ /// Hide the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Hide the matched elements with a sliding motion.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ },
+ 'stop': function() {
+ ///
+ /// Stop the currently-running animation on the matched elements.
+ /// A Boolean indicating whether to remove queued animation as well. Defaults to false.
+ /// A Boolean indicating whether to complete the current animation immediately. Defaults to false.
+ ///
+ ///
+ ///
+ /// Stop the currently-running animation on the matched elements.
+ /// The name of the queue in which to stop animations.
+ /// A Boolean indicating whether to remove queued animation as well. Defaults to false.
+ /// A Boolean indicating whether to complete the current animation immediately. Defaults to false.
+ ///
+ ///
+ },
+ 'submit': function() {
+ ///
+ /// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "submit" JavaScript event, or trigger that event on an element.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'text': function() {
+ ///
+ /// Set the content of each element in the set of matched elements to the specified text.
+ /// A string of text to set as the content of each matched element.
+ ///
+ ///
+ ///
+ /// Set the content of each element in the set of matched elements to the specified text.
+ /// A function returning the text content to set. Receives the index position of the element in the set and the old text value as arguments.
+ ///
+ ///
+ },
+ 'toArray': function() {
+ /// Retrieve all the DOM elements contained in the jQuery set, as an array.
+ ///
+ },
+ 'toggle': function() {
+ ///
+ /// Display or hide the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display or hide the matched elements.
+ /// A string or number determining how long the animation will run.
+ /// A string indicating which easing function to use for the transition.
+ /// A function to call once the animation is complete.
+ ///
+ ///
+ ///
+ /// Display or hide the matched elements.
+ /// A Boolean indicating whether to show or hide the elements.
+ ///
+ ///
+ },
+ 'toggleClass': function() {
+ ///
+ /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument.
+ /// One or more class names (separated by spaces) to be toggled for each element in the matched set.
+ ///
+ ///
+ ///
+ /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument.
+ /// One or more class names (separated by spaces) to be toggled for each element in the matched set.
+ /// A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed.
+ ///
+ ///
+ ///
+ /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument.
+ /// A boolean value to determine whether the class should be added or removed.
+ ///
+ ///
+ ///
+ /// Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument.
+ /// A function that returns class names to be toggled in the class attribute of each element in the matched set. Receives the index position of the element in the set, the old class value, and the switch as arguments.
+ /// A boolean value to determine whether the class should be added or removed.
+ ///
+ ///
+ },
+ 'trigger': function() {
+ ///
+ /// Execute all handlers and behaviors attached to the matched elements for the given event type.
+ /// A string containing a JavaScript event type, such as click or submit.
+ /// Additional parameters to pass along to the event handler.
+ ///
+ ///
+ ///
+ /// Execute all handlers and behaviors attached to the matched elements for the given event type.
+ /// A jQuery.Event object.
+ ///
+ ///
+ },
+ 'triggerHandler': function() {
+ ///
+ /// Execute all handlers attached to an element for an event.
+ /// A string containing a JavaScript event type, such as click or submit.
+ /// An array of additional parameters to pass along to the event handler.
+ ///
+ ///
+ },
+ 'unbind': function() {
+ ///
+ /// Remove a previously-attached event handler from the elements.
+ /// A string containing a JavaScript event type, such as click or submit.
+ /// The function that is to be no longer executed.
+ ///
+ ///
+ ///
+ /// Remove a previously-attached event handler from the elements.
+ /// A string containing a JavaScript event type, such as click or submit.
+ /// Unbinds the corresponding 'return false' function that was bound using .bind( eventType, false ).
+ ///
+ ///
+ ///
+ /// Remove a previously-attached event handler from the elements.
+ /// A JavaScript event object as passed to an event handler.
+ ///
+ ///
+ },
+ 'undelegate': function() {
+ ///
+ /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements.
+ /// A selector which will be used to filter the event results.
+ /// A string containing a JavaScript event type, such as "click" or "keydown"
+ ///
+ ///
+ ///
+ /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements.
+ /// A selector which will be used to filter the event results.
+ /// A string containing a JavaScript event type, such as "click" or "keydown"
+ /// A function to execute at the time the event is triggered.
+ ///
+ ///
+ ///
+ /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements.
+ /// A selector which will be used to filter the event results.
+ /// A map of one or more event types and previously bound functions to unbind from them.
+ ///
+ ///
+ ///
+ /// Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements.
+ /// A string containing a namespace to unbind all events from.
+ ///
+ ///
+ },
+ 'unload': function() {
+ ///
+ /// Bind an event handler to the "unload" JavaScript event.
+ /// A function to execute when the event is triggered.
+ ///
+ ///
+ ///
+ /// Bind an event handler to the "unload" JavaScript event.
+ /// A map of data that will be passed to the event handler.
+ /// A function to execute each time the event is triggered.
+ ///
+ ///
+ },
+ 'unwrap': function() {
+ /// Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place.
+ ///
+ },
+ 'val': function() {
+ ///
+ /// Set the value of each element in the set of matched elements.
+ /// A string of text or an array of strings corresponding to the value of each matched element to set as selected/checked.
+ ///
+ ///
+ ///
+ /// Set the value of each element in the set of matched elements.
+ /// A function returning the value to set. this is the current element. Receives the index position of the element in the set and the old value as arguments.
+ ///
+ ///
+ },
+ 'visible': function() {
+ /// Selects all elements that are visible.
+ },
+ 'width': function() {
+ ///
+ /// Set the CSS width of each element in the set of matched elements.
+ /// An integer representing the number of pixels, or an integer along with an optional unit of measure appended (as a string).
+ ///
+ ///
+ ///
+ /// Set the CSS width of each element in the set of matched elements.
+ /// A function returning the width to set. Receives the index position of the element in the set and the old width as arguments. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'wrap': function() {
+ ///
+ /// Wrap an HTML structure around each element in the set of matched elements.
+ /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements.
+ ///
+ ///
+ ///
+ /// Wrap an HTML structure around each element in the set of matched elements.
+ /// A callback function returning the HTML content or jQuery object to wrap around the matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+ 'wrapAll': function() {
+ ///
+ /// Wrap an HTML structure around all elements in the set of matched elements.
+ /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the matched elements.
+ ///
+ ///
+ },
+ 'wrapInner': function() {
+ ///
+ /// Wrap an HTML structure around the content of each element in the set of matched elements.
+ /// An HTML snippet, selector expression, jQuery object, or DOM element specifying the structure to wrap around the content of the matched elements.
+ ///
+ ///
+ ///
+ /// Wrap an HTML structure around the content of each element in the set of matched elements.
+ /// A callback function which generates a structure to wrap around the content of the matched elements. Receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set.
+ ///
+ ///
+ },
+});
+
+intellisense.annotate(window, {
+ '$': function() {
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A string containing a selector expression
+ /// A DOM Element, Document, or jQuery to use as context
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A DOM element to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// A plain object to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// An array containing a set of DOM elements to wrap in a jQuery object.
+ ///
+ ///
+ ///
+ /// Accepts a string containing a CSS selector which is then used to match a set of elements.
+ /// An existing jQuery object to clone.
+ ///
+ ///
+ },
+});
+
diff --git a/EFMVC.Web.API/Scripts/jquery-1.8.2.js b/EFMVC.Web.API/Scripts/jquery-1.8.2.js
new file mode 100644
index 0000000..12c7797
--- /dev/null
+++ b/EFMVC.Web.API/Scripts/jquery-1.8.2.js
@@ -0,0 +1,9440 @@
+/*!
+ * jQuery JavaScript Library v1.8.2
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time)
+ */
+(function( window, undefined ) {
+var
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+ location = window.location,
+ navigator = window.navigator,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // Save a reference to some core methods
+ core_push = Array.prototype.push,
+ core_slice = Array.prototype.slice,
+ core_indexOf = Array.prototype.indexOf,
+ core_toString = Object.prototype.toString,
+ core_hasOwn = Object.prototype.hasOwnProperty,
+ core_trim = String.prototype.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
+
+ // Used for detecting and trimming whitespace
+ core_rnotwhite = /\S/,
+ core_rspace = /\s+/,
+
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over to avoid XSS via location.hash (#9521)
+ rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // The ready event handler and self cleanup method
+ DOMContentLoaded = function() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ } else if ( document.readyState === "complete" ) {
+ // we're here because readyState === "complete" in oldIE
+ // which is good enough for us to call the dom ready!
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ },
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context && context.nodeType ? context.ownerDocument || context : document );
+
+ // scripts is true for back-compat
+ selector = jQuery.parseHTML( match[1], doc, true );
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ this.attr.call( selector, context, true );
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.8.2",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ eq: function( i ) {
+ i = +i;
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ),
+ "slice", core_slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ core_toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !core_hasOwn.call(obj, "constructor") &&
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || core_hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // scripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, scripts ) {
+ var parsed;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ scripts = context;
+ context = 0;
+ }
+ context = context || document;
+
+ // Single tag
+ if ( (parsed = rsingleTag.exec( data )) ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
+ return jQuery.merge( [],
+ (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
+ },
+
+ parseJSON: function( data ) {
+ if ( !data || typeof data !== "string") {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && core_rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var name,
+ i = 0,
+ length = obj.length,
+ isObj = length === undefined || jQuery.isFunction( obj );
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in obj ) {
+ if ( callback.apply( obj[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( obj[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in obj ) {
+ if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+ function( text ) {
+ return text == null ?
+ "" :
+ core_trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var type,
+ ret = results || [];
+
+ if ( arr != null ) {
+ // The window, strings (and functions) also have 'length'
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ type = jQuery.type( arr );
+
+ if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
+ core_push.call( ret, arr );
+ } else {
+ jQuery.merge( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( core_indexOf ) {
+ return core_indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key,
+ ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+ var exec,
+ bulk = key == null,
+ i = 0,
+ length = elems.length;
+
+ // Sets many values
+ if ( key && typeof key === "object" ) {
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+ }
+ chainable = 1;
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = pass === undefined && jQuery.isFunction( value );
+
+ if ( bulk ) {
+ // Bulk operations only iterate when executing function values
+ if ( exec ) {
+ exec = fn;
+ fn = function( elem, key, value ) {
+ return exec.call( jQuery( elem ), value );
+ };
+
+ // Otherwise they run against the entire set
+ } else {
+ fn.call( elems, value );
+ fn = null;
+ }
+ }
+
+ if ( fn ) {
+ for (; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+ }
+
+ chainable = 1;
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ }
+});
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready, 1 );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.split( core_rspace ), function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) {
+ list.push( arg );
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ return jQuery.inArray( fn, list ) > -1;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( list && ( !fired || stack ) ) {
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
+ function() {
+ var returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ } :
+ newDefer[ action ]
+ );
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ] = list.fire
+ deferred[ tuple[0] ] = list.fire;
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+jQuery.support = (function() {
+
+ var support,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ fragment,
+ eventName,
+ i,
+ isSupported,
+ clickFn,
+ div = document.createElement("div");
+
+ // Preliminary tests
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " a ";
+
+ all = div.getElementsByTagName("*");
+ a = div.getElementsByTagName("a")[ 0 ];
+ a.style.cssText = "top:1px;float:left;opacity:.5";
+
+ // Can't get basic test support
+ if ( !all || !all.length ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.5/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>",
+
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+ boxModel: ( document.compatMode === "CSS1Compat" ),
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true,
+ boxSizingReliable: true,
+ pixelPosition: false
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", clickFn = function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent("onclick");
+ div.detachEvent( "onclick", clickFn );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+
+ input.setAttribute( "checked", "checked" );
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ fragment.removeChild( input );
+ fragment.appendChild( div );
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for ( i in {
+ submit: true,
+ change: true,
+ focusin: true
+ }) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, div, tds, marginDiv,
+ divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct the test element
+ div = document.createElement("div");
+ container.appendChild( div );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ div.innerHTML = "";
+ tds = div.getElementsByTagName("td");
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE <= 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Check box-sizing and margin behavior
+ div.innerHTML = "";
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+ support.boxSizing = ( div.offsetWidth === 4 );
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+ // NOTE: To any future maintainer, we've window.getComputedStyle
+ // because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = document.createElement("div");
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ if ( typeof div.style.zoom !== "undefined" ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.innerHTML = "";
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "block";
+ div.style.overflow = "visible";
+ div.innerHTML = "
";
+ div.firstChild.style.width = "5px";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+ container.style.zoom = 1;
+ }
+
+ // Null elements to avoid leaks in IE
+ body.removeChild( container );
+ container = div = tds = marginDiv = null;
+ });
+
+ // Null elements to avoid leaks in IE
+ fragment.removeChild( div );
+ all = a = select = opt = input = fragment = div = null;
+
+ return support;
+})();
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+ cache: {},
+
+ deletedIds: [],
+
+ // Remove at next major release (1.9/2.0)
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ // nodes accept data unless otherwise specified; rejection can be conditional
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, part, attr, name, l,
+ elem = this[0],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ attr = elem.attributes;
+ for ( l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( !name.indexOf( "data-" ) ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split( ".", 2 );
+ parts[1] = parts[1] ? "." + parts[1] : "";
+ part = parts[1] + "!";
+
+ return jQuery.access( this, function( value ) {
+
+ if ( value === undefined ) {
+ data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && elem ) {
+ data = jQuery.data( elem, key );
+ data = dataAttr( elem, key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ }
+
+ parts[1] = value;
+ this.each(function() {
+ var self = jQuery( this );
+
+ self.triggerHandler( "setData" + part, parts );
+ jQuery.data( this, key, value );
+ self.triggerHandler( "changeData" + part, parts );
+ });
+ }, null, value, arguments.length > 1, null, false );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery.removeData( elem, type + "queue", true );
+ jQuery.removeData( elem, key, true );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var nodeHook, boolHook, fixSpecified,
+ rclass = /[\t\r\n]/g,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea|)$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( core_rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var removes, className, elem, c, cl, i, l;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+ if ( (value && typeof value === "string") || value === undefined ) {
+ removes = ( value || "" ).split( core_rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+ if ( elem.nodeType === 1 && elem.className ) {
+
+ className = (" " + elem.className + " ").replace( rclass, " " );
+
+ // loop over each item in the removal list
+ for ( c = 0, cl = removes.length; c < cl; c++ ) {
+ // Remove until there is nothing to remove,
+ while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
+ className = className.replace( " " + removes[ c ] + " " , " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( className ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( core_rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val,
+ self = jQuery(this);
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
+ attrFn: {},
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, isBool,
+ i = 0;
+
+ if ( value && elem.nodeType === 1 ) {
+
+ attrNames = value.split( core_rspace );
+
+ for ( ; i < attrNames.length; i++ ) {
+ name = attrNames[ i ];
+
+ if ( name ) {
+ propName = jQuery.propFix[ name ] || name;
+ isBool = rboolean.test( name );
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ // Do not do this for boolean attributes (see #10870)
+ if ( !isBool ) {
+ jQuery.attr( elem, name, "" );
+ }
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( isBool && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true,
+ coords: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
+ ret.value :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.value = value + "" );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+var rformElems = /^(?:textarea|input|select)$/i,
+ rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
+ rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = jQuery.trim( hoverHack(types) ).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var t, tns, type, origType, namespaces, origCount,
+ j, events, special, eventType, handleObj,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+
+ // Remove matching events
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, "events", true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
+ type = event.type || event,
+ namespaces = [];
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+ for ( old = elem; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old === (elem.ownerDocument || document) ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ // Note that this is a bare JS function and not a jQuery handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
+ handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = core_slice.call( arguments ),
+ run_all = !event.exclusive && !event.namespace,
+ special = jQuery.event.special[ event.type ] || {},
+ handlerQueue = [];
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !(event.button && event.type === "click") ) {
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+
+ // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.disabled !== true || event.type !== "click" ) {
+ selMatch = {};
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+
+ if ( selMatch[ sel ] === undefined ) {
+ selMatch[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( selMatch[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+
+ focus: {
+ delegateType: "focusin"
+ },
+ blur: {
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8 –
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === "undefined" ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "_submit_attached" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "_submit_attached", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "_change_attached", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) { // && selector != null
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://sizzlejs.com/
+ */
+(function( window, undefined ) {
+
+var cachedruns,
+ assertGetIdNotName,
+ Expr,
+ getText,
+ isXML,
+ contains,
+ compile,
+ sortOrder,
+ hasDuplicate,
+ outermostContext,
+
+ baseHasDuplicate = true,
+ strundefined = "undefined",
+
+ expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
+
+ Token = String,
+ document = window.document,
+ docElem = document.documentElement,
+ dirruns = 0,
+ done = 0,
+ pop = [].pop,
+ push = [].push,
+ slice = [].slice,
+ // Use a stripped-down indexOf if a native one is unavailable
+ indexOf = [].indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ // Augment a function for special use by Sizzle
+ markFunction = function( fn, value ) {
+ fn[ expando ] = value == null || value;
+ return fn;
+ },
+
+ createCache = function() {
+ var cache = {},
+ keys = [];
+
+ return markFunction(function( key, value ) {
+ // Only keep the most recent entries
+ if ( keys.push( key ) > Expr.cacheLength ) {
+ delete cache[ keys.shift() ];
+ }
+
+ return (cache[ key ] = value);
+ }, cache );
+ },
+
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+
+ // Regex
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ operators = "([*^$|!~]?=)",
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments not in parens/brackets,
+ // then attribute selectors and non-pseudos (denoted by :),
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
+
+ // For matchExpr.POS and matchExpr.needsContext
+ pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
+ "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
+ rpseudo = new RegExp( pseudos ),
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
+
+ rnot = /^:not/,
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
+ rendsWithNot = /:not\($/,
+
+ rheader = /h\d/i,
+ rinputs = /input|select|textarea|button/i,
+
+ rbackslash = /\\(?!\\)/g,
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "POS": new RegExp( pos, "i" ),
+ "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ // For use in libraries implementing .is()
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
+ },
+
+ // Support
+
+ // Used for testing something on an element
+ assert = function( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // release memory in IE
+ div = null;
+ }
+ },
+
+ // Check if getElementsByTagName("*") returns only elements
+ assertTagNameNoComments = assert(function( div ) {
+ div.appendChild( document.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ }),
+
+ // Check if getAttribute returns normalized href attributes
+ assertHrefNotNormalized = assert(function( div ) {
+ div.innerHTML = " ";
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
+ div.firstChild.getAttribute("href") === "#";
+ }),
+
+ // Check if attributes should be retrieved by attribute nodes
+ assertAttributes = assert(function( div ) {
+ div.innerHTML = " ";
+ var type = typeof div.lastChild.getAttribute("multiple");
+ // IE8 returns a string for some attributes even when not present
+ return type !== "boolean" && type !== "string";
+ }),
+
+ // Check if getElementsByClassName can be trusted
+ assertUsableClassName = assert(function( div ) {
+ // Opera can't find a second classname (in 9.6)
+ div.innerHTML = "
";
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
+ return false;
+ }
+
+ // Safari 3.2 caches class attributes and doesn't catch changes
+ div.lastChild.className = "e";
+ return div.getElementsByClassName("e").length === 2;
+ }),
+
+ // Check if getElementById returns elements by name
+ // Check if getElementsByName privileges form controls or returns elements by ID
+ assertUsableName = assert(function( div ) {
+ // Inject content
+ div.id = expando + 0;
+ div.innerHTML = "
";
+ docElem.insertBefore( div, docElem.firstChild );
+
+ // Test
+ var pass = document.getElementsByName &&
+ // buggy browsers will return fewer than the correct 2
+ document.getElementsByName( expando ).length === 2 +
+ // buggy browsers will return more than the correct 0
+ document.getElementsByName( expando + 0 ).length;
+ assertGetIdNotName = !document.getElementById( expando );
+
+ // Cleanup
+ docElem.removeChild( div );
+
+ return pass;
+ });
+
+// If slice is not available, provide a backup
+try {
+ slice.call( docElem.childNodes, 0 )[0].nodeType;
+} catch ( e ) {
+ slice = function( i ) {
+ var elem,
+ results = [];
+ for ( ; (elem = this[i]); i++ ) {
+ results.push( elem );
+ }
+ return results;
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+ var match, elem, xml, m,
+ nodeType = context.nodeType;
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( nodeType !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ xml = isXML( context );
+
+ if ( !xml && !seed ) {
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
+ return results;
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );
+}
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ return Sizzle( expr, null, null, [ elem ] ).length > 0;
+};
+
+// Returns a function to use in pseudos for input types
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for buttons
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+// Returns a function to use in pseudos for positionals
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( nodeType ) {
+ if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ }
+ return ret;
+};
+
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+// Element contains another
+contains = Sizzle.contains = docElem.contains ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
+ } :
+ docElem.compareDocumentPosition ?
+ function( a, b ) {
+ return b && !!( a.compareDocumentPosition( b ) & 16 );
+ } :
+ function( a, b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+Sizzle.attr = function( elem, name ) {
+ var val,
+ xml = isXML( elem );
+
+ if ( !xml ) {
+ name = name.toLowerCase();
+ }
+ if ( (val = Expr.attrHandle[ name ]) ) {
+ return val( elem );
+ }
+ if ( xml || assertAttributes ) {
+ return elem.getAttribute( name );
+ }
+ val = elem.getAttributeNode( name );
+ return val ?
+ typeof elem[ name ] === "boolean" ?
+ elem[ name ] ? name : null :
+ val.specified ? val.value : null :
+ null;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ // IE6/7 return a modified href
+ attrHandle: assertHrefNotNormalized ?
+ {} :
+ {
+ "href": function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ },
+ "type": function( elem ) {
+ return elem.getAttribute("type");
+ }
+ },
+
+ find: {
+ "ID": assertGetIdNotName ?
+ function( id, context, xml ) {
+ if ( typeof context.getElementById !== strundefined && !xml ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ } :
+ function( id, context, xml ) {
+ if ( typeof context.getElementById !== strundefined && !xml ) {
+ var m = context.getElementById( id );
+
+ return m ?
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
+ [m] :
+ undefined :
+ [];
+ }
+ },
+
+ "TAG": assertTagNameNoComments ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ var elem,
+ tmp = [],
+ i = 0;
+
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ },
+
+ "NAME": assertUsableName && function( tag, context ) {
+ if ( typeof context.getElementsByName !== strundefined ) {
+ return context.getElementsByName( name );
+ }
+ },
+
+ "CLASS": assertUsableClassName && function( className, context, xml ) {
+ if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
+ return context.getElementsByClassName( className );
+ }
+ }
+ },
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( rbackslash, "" );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 3 xn-component of xn+y argument ([+-]?\d*n|)
+ 4 sign of xn-component
+ 5 x of xn-component
+ 6 sign of y-component
+ 7 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1] === "nth" ) {
+ // nth-child requires argument
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
+ match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var unquoted, excess;
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ if ( match[3] ) {
+ match[2] = match[3];
+ } else if ( (unquoted = match[4]) ) {
+ // Only check arguments that contain a pseudo
+ if ( rpseudo.test(unquoted) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ unquoted = unquoted.slice( 0, excess );
+ match[0] = match[0].slice( 0, excess );
+ }
+ match[2] = unquoted;
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+ "ID": assertGetIdNotName ?
+ function( id ) {
+ id = id.replace( rbackslash, "" );
+ return function( elem ) {
+ return elem.getAttribute("id") === id;
+ };
+ } :
+ function( id ) {
+ id = id.replace( rbackslash, "" );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === id;
+ };
+ },
+
+ "TAG": function( nodeName ) {
+ if ( nodeName === "*" ) {
+ return function() { return true; };
+ }
+ nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();
+
+ return function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ expando ][ className ];
+ if ( !pattern ) {
+ pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") );
+ }
+ return function( elem ) {
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
+ };
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem, context ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.substr( result.length - check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, argument, first, last ) {
+
+ if ( type === "nth" ) {
+ return function( elem ) {
+ var node, diff,
+ parent = elem.parentNode;
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ if ( parent ) {
+ diff = 0;
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ diff++;
+ if ( elem === node ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset (or cast to NaN), then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ };
+ }
+
+ return function( elem ) {
+ var node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ /* falls through */
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ var nodeType;
+ elem = elem.firstChild;
+ while ( elem ) {
+ if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {
+ return false;
+ }
+ elem = elem.nextSibling;
+ }
+ return true;
+ },
+
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "text": function( elem ) {
+ var type, attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ (type = elem.type) === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
+ },
+
+ // Input types
+ "radio": createInputPseudo("radio"),
+ "checkbox": createInputPseudo("checkbox"),
+ "file": createInputPseudo("file"),
+ "password": createInputPseudo("password"),
+ "image": createInputPseudo("image"),
+
+ "submit": createButtonPseudo("submit"),
+ "reset": createButtonPseudo("reset"),
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "focus": function( elem ) {
+ var doc = elem.ownerDocument;
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
+ },
+
+ "active": function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
+ },
+
+ // Positional types
+ "first": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ for ( var i = 0; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ for ( var i = 1; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+function siblingCheck( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+}
+
+sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
+ a.compareDocumentPosition :
+ a.compareDocumentPosition(b) & 4
+ ) ? -1 : 1;
+ } :
+ function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
+
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+// Always assume the presence of duplicates if sort doesn't
+// pass them to our comparison function (as in Google Chrome).
+[0, 0].sort( sortOrder );
+baseHasDuplicate = !hasDuplicate;
+
+// Document sorting and removing duplicates
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ i = 1;
+
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( ; (elem = results[i]); i++ ) {
+ if ( elem === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type, soFar, groups, preFilters,
+ cached = tokenCache[ expando ][ selector ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ soFar = soFar.slice( match[0].length );
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ tokens.push( matched = new Token( match.shift() ) );
+ soFar = soFar.slice( matched.length );
+
+ // Cast descendant combinators to space
+ matched.type = match[0].replace( rtrim, " " );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ // The last two arguments here are (context, xml) for backCompat
+ (match = preFilters[ type ]( match, document, true ))) ) {
+
+ tokens.push( matched = new Token( match.shift() ) );
+ soFar = soFar.slice( matched.length );
+ matched.type = type;
+ matched.matches = match;
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && combinator.dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( checkNonElements || elem.nodeType === 1 ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( !xml ) {
+ var cache,
+ dirkey = dirruns + " " + doneName + " ",
+ cachedkey = dirkey + cachedruns;
+ while ( (elem = elem[ dir ]) ) {
+ if ( checkNonElements || elem.nodeType === 1 ) {
+ if ( (cache = elem[ expando ]) === cachedkey ) {
+ return elem.sizset;
+ } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
+ if ( elem.sizset ) {
+ return elem;
+ }
+ } else {
+ elem[ expando ] = cachedkey;
+ if ( matcher( elem, context, xml ) ) {
+ elem.sizset = true;
+ return elem;
+ }
+ elem.sizset = false;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( checkNonElements || elem.nodeType === 1 ) {
+ if ( matcher( elem, context, xml ) ) {
+ return elem;
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones
+ if ( seed && postFinder ) {
+ return;
+ }
+
+ var i, elem, postFilterIn,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ postFilterIn = condense( matcherOut, postMap );
+ postFilter( postFilterIn, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = postFilterIn.length;
+ while ( i-- ) {
+ if ( (elem = postFilterIn[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ // Keep seed and results synchronized
+ if ( seed ) {
+ // Ignore postFinder because it can't coexist with seed
+ i = preFilter && matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ seed[ preMap[i] ] = !(results[ preMap[i] ] = elem);
+ }
+ }
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
+ } else {
+ // The concatenated values are (context, xml) for backCompat
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && tokens.join("")
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Nested matchers should use non-integer dirruns
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = superMatcher.el;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ for ( j = 0; (matcher = elementMatchers[j]); j++ ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++superMatcher.el;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ for ( j = 0; (matcher = setMatchers[j]); j++ ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ superMatcher.el = 0;
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ expando ][ selector ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+};
+
+function multipleContexts( selector, contexts, results, seed ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results, seed );
+ }
+ return results;
+}
+
+function select( selector, context, results, seed, xml ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector ),
+ j = match.length;
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && !xml &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];
+ if ( !context ) {
+ return results;
+ }
+
+ selector = selector.slice( tokens.shift().length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( rbackslash, "" ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context,
+ xml
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && tokens.join("");
+ if ( !selector ) {
+ push.apply( results, slice.call( seed, 0 ) );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ xml,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+}
+
+if ( document.querySelectorAll ) {
+ (function() {
+ var disconnectedMatch,
+ oldSelect = select,
+ rescape = /'|\\/g,
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
+
+ // qSa(:focus) reports false when true (Chrome 21),
+ // A support test would require too much code (would include document ready)
+ rbuggyQSA = [":focus"],
+
+ // matchesSelector(:focus) reports false when true (Chrome 21),
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ // A support test would require too much code (would include document ready)
+ // just skip matchesSelector for :active
+ rbuggyMatches = [ ":active", ":focus" ],
+ matches = docElem.matchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.webkitMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector;
+
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explictly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = " ";
+
+ // IE8 - Some boolean attributes are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here (do not put tests after this one)
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Opera 10-12/IE9 - ^= $= *= and empty values
+ // Should not select anything
+ div.innerHTML = "
";
+ if ( div.querySelectorAll("[test^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here (do not put tests after this one)
+ div.innerHTML = " ";
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push(":enabled", ":disabled");
+ }
+ });
+
+ // rbuggyQSA always contains :focus, so no need for a length check
+ rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );
+
+ select = function( selector, context, results, seed, xml ) {
+ // Only use querySelectorAll when not filtering,
+ // when this is not xml,
+ // and when no QSA bugs apply
+ if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ var groups, i,
+ old = true,
+ nid = expando,
+ newContext = context,
+ newSelector = context.nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + groups[i].join("");
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results, slice.call( newContext.querySelectorAll(
+ newSelector
+ ), 0 ) );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+
+ return oldSelect( selector, context, results, seed, xml );
+ };
+
+ if ( matches ) {
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ try {
+ matches.call( div, "[test!='']:sizzle" );
+ rbuggyMatches.push( "!=", pseudos );
+ } catch ( e ) {}
+ });
+
+ // rbuggyMatches always contains :active and :focus, so no need for a length check
+ rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
+
+ Sizzle.matchesSelector = function( elem, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ // rbuggyMatches always contains :active, so no need for an existence check
+ if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, null, null, [ elem ] ).length > 0;
+ };
+ }
+ })();
+}
+
+// Deprecated
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Back-compat
+function setFilters() {}
+Expr.filters = setFilters.prototype = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i, l, length, n, r, ret,
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ });
+ }
+
+ ret = this.pushStack( "", "find", selector );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ rneedsContext.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ ret = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+ }
+ cur = cur.parentNode;
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = / ]", "i"),
+ rcheckableType = /^(?:checkbox|radio)$/,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*\s*$/g,
+ wrapMap = {
+ option: [ 1, "", " " ],
+ legend: [ 1, "", " " ],
+ thead: [ 1, "" ],
+ tr: [ 2, "" ],
+ td: [ 3, "" ],
+ col: [ 2, "" ],
+ area: [ 1, "", " " ],
+ _default: [ 0, "", "" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+// unless wrapped in a div with non-breaking characters in front of it.
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "X", "
" ];
+}
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( !isDisconnected( this[0] ) ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ }
+
+ if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
+ }
+ },
+
+ after: function() {
+ if ( !isDisconnected( this[0] ) ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ }
+
+ if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[0] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1>$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName( "*" ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function( value ) {
+ if ( !isDisconnected( this[0] ) ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ }
+
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+
+ // Flatten any nested arrays
+ args = [].concat.apply( [], args );
+
+ var results, first, fragment, iNoClone,
+ i = 0,
+ value = args[0],
+ scripts = [],
+ l = this.length;
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call( this, i, table ? self.html() : undefined );
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ results = jQuery.buildFragment( args, this, scripts );
+ fragment = results.fragment;
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ // Fragments from the fragment cache must always be cloned and never used in place.
+ for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
+ callback.call(
+ table && jQuery.nodeName( this[i], "table" ) ?
+ findOrAppend( this[i], "tbody" ) :
+ this[i],
+ i === iNoClone ?
+ fragment :
+ jQuery.clone( fragment, true, true )
+ );
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, function( i, elem ) {
+ if ( elem.src ) {
+ if ( jQuery.ajax ) {
+ jQuery.ajax({
+ url: elem.src,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ } else {
+ jQuery.error("no ajax");
+ }
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ });
+ }
+ }
+
+ return this;
+ }
+});
+
+function findOrAppend( elem, tag ) {
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function cloneFixAttributes( src, dest ) {
+ var nodeName;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
+ }
+
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ if ( nodeName === "object" ) {
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+
+ // IE blanks contents when cloning scripts
+ } else if ( nodeName === "script" && dest.text !== src.text ) {
+ dest.text = src.text;
+ }
+
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, context, scripts ) {
+ var fragment, cacheable, cachehit,
+ first = args[ 0 ];
+
+ // Set context from what may come in as undefined or a jQuery collection or a node
+ // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
+ // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
+ context = context || document;
+ context = !context.nodeType && context[0] || context;
+ context = context.ownerDocument || context;
+
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put or elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+ // Mark cacheable and look for a hit
+ cacheable = true;
+ fragment = jQuery.fragments[ first ];
+ cachehit = fragment !== undefined;
+ }
+
+ if ( !fragment ) {
+ fragment = context.createDocumentFragment();
+ jQuery.clean( args, context, fragment, scripts );
+
+ // Update the cache, but only store false
+ // unless this is a second parsing of the same content
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cachehit && fragment;
+ }
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ l = insert.length,
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+ } else {
+ for ( ; i < l; i++ ) {
+ elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
+
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
+
+ } else {
+ return [];
+ }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var srcElements,
+ destElements,
+ i,
+ clone;
+
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
+
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
+
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ srcElements = destElements = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ clean: function( elems, context, fragment, scripts ) {
+ var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
+ safe = context === document && safeFragment,
+ ret = [];
+
+ // Ensure that context is a document
+ if ( !context || typeof context.createDocumentFragment === "undefined" ) {
+ context = document;
+ }
+
+ // Use the already-created safe fragment if context permits
+ for ( i = 0; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Ensure a safe container in which to render the html
+ safe = safe || createSafeFragment( context );
+ div = context.createElement("div");
+ safe.appendChild( div );
+
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1>$2>");
+
+ // Go to html and back, then peel off extra wrappers
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ depth = wrap[0];
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a , *may* have spurious
+ hasBody = rtbody.test(elem);
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare or
+ wrap[1] === "" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+
+ // Take out of fragment container (we need a fresh div each time)
+ div.parentNode.removeChild( div );
+ }
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ jQuery.merge( ret, elem );
+ }
+ }
+
+ // Fix #11356: Clear elements from safeFragment
+ if ( div ) {
+ elem = div = safe = null;
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !jQuery.support.appendChecked ) {
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ fixDefaultChecked( elem );
+ } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ }
+ }
+ }
+
+ // Append elements to a provided document fragment
+ if ( fragment ) {
+ // Special handling of each script element
+ handleScript = function( elem ) {
+ // Check if we consider it executable
+ if ( !elem.type || rscriptType.test( elem.type ) ) {
+ // Detach the script and store it in the scripts array (if provided) or the fragment
+ // Return truthy to indicate that it has been handled
+ return scripts ?
+ scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
+ fragment.appendChild( elem );
+ }
+ };
+
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
+ // Check if we're done after handling an executable script
+ if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
+ // Append to fragment and handle embedded scripts
+ fragment.appendChild( elem );
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
+ jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
+
+ // Splice the scripts into ret after their former ancestor and advance our index beyond them
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ i += jsTags.length;
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var data, id, elem, type,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = jQuery.support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ jQuery.deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+// Limit scope pollution from any deprecated API
+(function() {
+
+var matched, browser;
+
+// Use of jQuery.browser is frowned upon.
+// More details: http://api.jquery.com/jQuery.browser
+// jQuery.uaMatch maintained for back-compat
+jQuery.uaMatch = function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+};
+
+matched = jQuery.uaMatch( navigator.userAgent );
+browser = {};
+
+if ( matched.browser ) {
+ browser[ matched.browser ] = true;
+ browser.version = matched.version;
+}
+
+// Chrome is Webkit, but Webkit is also Safari.
+if ( browser.chrome ) {
+ browser.webkit = true;
+} else if ( browser.webkit ) {
+ browser.safari = true;
+}
+
+jQuery.browser = browser;
+
+jQuery.sub = function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+};
+
+})();
+var curCSS, iframe, iframeDoc,
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ rposition = /^(top|right|bottom|left)$/,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
+ elemdisplay = {},
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+
+ eventsToggle = jQuery.fn.toggle;
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function isHidden( elem, el ) {
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+ var elem, display,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && elem.style.display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+ display = curCSS( elem, "display" );
+
+ if ( !values[ index ] && display !== "none" ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state, fn2 ) {
+ var bool = typeof state === "boolean";
+
+ if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
+ return eventsToggle.apply( this, arguments );
+ }
+
+ return this.each(function() {
+ if ( bool ? state : isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, numeric, extra ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( numeric || extra !== undefined ) {
+ num = parseFloat( val );
+ return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+// NOTE: To any future maintainer, we've window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+ curCSS = function( elem, name ) {
+ var ret, width, minWidth, maxWidth,
+ computed = window.getComputedStyle( elem, null ),
+ style = elem.style;
+
+ if ( computed ) {
+
+ ret = computed[ name ];
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+ };
+} else if ( document.documentElement.currentStyle ) {
+ curCSS = function( elem, name ) {
+ var left, rsLeft,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ // we use jQuery.css instead of curCSS here
+ // because of the reliableMarginRight CSS hook!
+ val += jQuery.css( elem, extra + cssExpand[ i ], true );
+ }
+
+ // From this point on we use curCSS for maximum performance (relevant in animations)
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ valueIsBorderBox = true,
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox
+ )
+ ) + "px";
+}
+
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+ if ( elemdisplay[ nodeName ] ) {
+ return elemdisplay[ nodeName ];
+ }
+
+ var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
+ display = elem.css("display");
+ elem.remove();
+
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // Use the already-created iframe if possible
+ iframe = document.body.appendChild(
+ iframe || jQuery.extend( document.createElement("iframe"), {
+ frameBorder: 0,
+ width: 0,
+ height: 0
+ })
+ );
+
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write("");
+ iframeDoc.close();
+ }
+
+ elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
+
+ display = curCSS( elem, "display" );
+ document.body.removeChild( iframe );
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+
+ return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
+ return jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ });
+ } else {
+ return getWidthOrHeight( elem, name, extra );
+ }
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ return curCSS( elem, "marginRight" );
+ }
+ });
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ var ret = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
+ }
+ }
+ };
+ });
+ }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i,
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ],
+ expanded = {};
+
+ for ( i = 0; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ rselectTextarea = /^(?:select|textarea)/i;
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /");
+ };
+
+ if (jQueryTmplVersion > 0) {
+ jQuery['tmpl']['tag']['ko_code'] = {
+ open: "__.push($1 || '');"
+ };
+ jQuery['tmpl']['tag']['ko_with'] = {
+ open: "with($1) {",
+ close: "} "
+ };
+ }
+ };
+
+ ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
+
+ // Use this one by default *only if jquery.tmpl is referenced*
+ var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
+ if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
+ ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
+
+ ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
+})();
+});
+})(window,document,navigator,window["jQuery"]);
+})();
diff --git a/EFMVC.Web.API/Scripts/knockout-2.2.0.js b/EFMVC.Web.API/Scripts/knockout-2.2.0.js
new file mode 100644
index 0000000..11f8bd8
--- /dev/null
+++ b/EFMVC.Web.API/Scripts/knockout-2.2.0.js
@@ -0,0 +1,85 @@
+// Knockout JavaScript library v2.2.0
+// (c) Steven Sanderson - http://knockoutjs.com/
+// License: MIT (http://www.opensource.org/licenses/mit-license.php)
+
+(function() {function i(v){throw v;}var l=!0,n=null,q=!1;function t(v){return function(){return v}};var w=window,x=document,fa=navigator,E=window.jQuery,H=void 0;
+function K(v){function ga(a,d,c,e,f){var g=[],a=b.j(function(){var a=d(c,f)||[];0 ",g[0];);m=4b.a.i(d,a[c])&&d.push(a[c]);return d},V:function(a,b){for(var a=a||[],d=[],c=0,e=a.length;cm?a.setAttribute("selected",b):a.selected=b},D:function(a){return(a||"").replace(d,"")},Qb:function(a,d){for(var c=[],e=(a||"").split(d),f=0,g=e.length;fa.length?q:a.substring(0,b.length)===b},sb:function(a,b){if(b.compareDocumentPosition)return 16==
+(b.compareDocumentPosition(a)&16);for(;a!=n;){if(a==b)return l;a=a.parentNode}return q},X:function(a){return b.a.sb(a,a.ownerDocument)},u:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,d,c){var e=m&&k[d];if(!e&&"undefined"!=typeof E){if(a(b,d))var f=c,c=function(a,b){var d=this.checked;b&&(this.checked=b.mb!==l);f.call(this,a);this.checked=d};E(b).bind(d,c)}else!e&&"function"==typeof b.addEventListener?b.addEventListener(d,c,q):"undefined"!=typeof b.attachEvent?b.attachEvent("on"+
+d,function(a){c.call(b,a)}):i(Error("Browser doesn't support addEventListener or attachEvent"))},Aa:function(b,d){(!b||!b.nodeType)&&i(Error("element must be a DOM node when calling triggerEvent"));if("undefined"!=typeof E){var c=[];a(b,d)&&c.push({mb:b.checked});E(b).trigger(d,c)}else"function"==typeof x.createEvent?"function"==typeof b.dispatchEvent?(c=x.createEvent(e[d]||"HTMLEvents"),c.initEvent(d,l,l,w,0,0,0,0,0,q,q,q,q,0,b),b.dispatchEvent(c)):i(Error("The supplied element doesn't support dispatchEvent")):
+"undefined"!=typeof b.fireEvent?(a(b,d)&&(b.checked=b.checked!==l),b.fireEvent("on"+d)):i(Error("Browser doesn't support triggering events"))},d:function(a){return b.$(a)?a():a},ta:function(a){return b.$(a)?a.t():a},da:function(a,d,c){if(d){var e=/[\w-]+/g,f=a.className.match(e)||[];b.a.o(d.match(e),function(a){var d=b.a.i(f,a);0<=d?c||f.splice(d,1):c&&f.push(a)});a.className=f.join(" ")}},bb:function(a,d){var c=b.a.d(d);if(c===n||c===H)c="";if(3===a.nodeType)a.data=c;else{var e=b.e.firstChild(a);
+!e||3!=e.nodeType||b.e.nextSibling(e)?b.e.N(a,[x.createTextNode(c)]):e.data=c;b.a.vb(a)}},$a:function(a,b){a.name=b;if(7>=m)try{a.mergeAttributes(x.createElement(" "),q)}catch(d){}},vb:function(a){9<=m&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},tb:function(a){if(9<=m){var b=a.style.width;a.style.width=0;a.style.width=b}},Kb:function(a,d){for(var a=b.a.d(a),d=b.a.d(d),c=[],e=a;e<=d;e++)c.push(e);return c},L:function(a){for(var b=[],d=0,c=a.length;d<
+c;d++)b.push(a[d]);return b},Ob:6===m,Pb:7===m,Z:m,Na:function(a,d){for(var c=b.a.L(a.getElementsByTagName("input")).concat(b.a.L(a.getElementsByTagName("textarea"))),e="string"==typeof d?function(a){return a.name===d}:function(a){return d.test(a.name)},f=[],g=c.length-1;0<=g;g--)e(c[g])&&f.push(c[g]);return f},Hb:function(a){return"string"==typeof a&&(a=b.a.D(a))?w.JSON&&w.JSON.parse?w.JSON.parse(a):(new Function("return "+a))():n},wa:function(a,d,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&
+i(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));return JSON.stringify(b.a.d(a),d,c)},Ib:function(a,d,c){var c=c||{},e=c.params||{},f=c.includeFields||this.Ma,g=a;if("object"==typeof a&&"form"===b.a.u(a))for(var g=a.action,h=f.length-1;0<=h;h--)for(var j=b.a.Na(a,f[h]),k=j.length-1;0<=k;k--)e[j[k].name]=j[k].value;var d=b.a.d(d),m=x.createElement("form");
+m.style.display="none";m.action=g;m.method="post";for(var v in d)a=x.createElement("input"),a.name=v,a.value=b.a.wa(b.a.d(d[v])),m.appendChild(a);for(v in e)a=x.createElement("input"),a.name=v,a.value=e[v],m.appendChild(a);x.body.appendChild(m);c.submitter?c.submitter(m):m.submit();setTimeout(function(){m.parentNode.removeChild(m)},0)}}};b.b("utils",b.a);b.b("utils.arrayForEach",b.a.o);b.b("utils.arrayFirst",b.a.kb);b.b("utils.arrayFilter",b.a.fa);b.b("utils.arrayGetDistinctValues",b.a.Fa);b.b("utils.arrayIndexOf",
+b.a.i);b.b("utils.arrayMap",b.a.V);b.b("utils.arrayPushAll",b.a.P);b.b("utils.arrayRemoveItem",b.a.ga);b.b("utils.extend",b.a.extend);b.b("utils.fieldsIncludedWithJsonPost",b.a.Ma);b.b("utils.getFormFields",b.a.Na);b.b("utils.peekObservable",b.a.ta);b.b("utils.postJson",b.a.Ib);b.b("utils.parseJson",b.a.Hb);b.b("utils.registerEventHandler",b.a.n);b.b("utils.stringifyJson",b.a.wa);b.b("utils.range",b.a.Kb);b.b("utils.toggleDomNodeCssClass",b.a.da);b.b("utils.triggerEvent",b.a.Aa);b.b("utils.unwrapObservable",
+b.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments),a=c.shift();return function(){return b.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});b.a.f=new function(){var a=0,d="__ko__"+(new Date).getTime(),c={};return{get:function(a,d){var c=b.a.f.getAll(a,q);return c===H?H:c[d]},set:function(a,d,c){c===H&&b.a.f.getAll(a,q)===H||(b.a.f.getAll(a,l)[d]=c)},getAll:function(b,f){var g=b[d];if(!g||!("null"!==g&&c[g])){if(!f)return H;
+g=b[d]="ko"+a++;c[g]={}}return c[g]},clear:function(a){var b=a[d];return b?(delete c[b],a[d]=n,l):q}}};b.b("utils.domData",b.a.f);b.b("utils.domData.clear",b.a.f.clear);b.a.F=new function(){function a(a,d){var e=b.a.f.get(a,c);e===H&&d&&(e=[],b.a.f.set(a,c,e));return e}function d(c){var e=a(c,q);if(e)for(var e=e.slice(0),j=0;j","
"]||!c.indexOf(" ","
"]||(!c.indexOf(" "," "]||[0,"",""];a="ignored"+c[1]+a+c[2]+"
";for("function"==typeof w.innerShiv?d.appendChild(w.innerShiv(a)):d.innerHTML=a;c[0]--;)d=d.lastChild;d=b.a.L(d.lastChild.childNodes)}return d};b.a.ca=function(a,d){b.a.ka(a);d=b.a.d(d);if(d!==n&&d!==H)if("string"!=typeof d&&(d=d.toString()),"undefined"!=typeof E)E(a).html(d);else for(var c=
+b.a.sa(d),e=0;e"},gb:function(a,b){var c=Q[a];c===H&&i(Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized."));
+try{return c.apply(n,b||[]),l}finally{delete Q[a]}},hb:function(a,d){var c=[];ba(a,c);for(var e=0,f=c.length;ec;c++)a=a();return a})};b.toJSON=function(a,d,c){a=b.fb(a);return b.a.wa(a,d,c)};b.b("toJS",b.fb);b.b("toJSON",b.toJSON);b.k={q:function(a){switch(b.a.u(a)){case "option":return a.__ko__hasDomDataOptionValue__===
+l?b.a.f.get(a,b.c.options.ra):7>=b.a.Z?a.getAttributeNode("value").specified?a.value:a.text:a.value;case "select":return 0<=a.selectedIndex?b.k.q(a.options[a.selectedIndex]):H;default:return a.value}},T:function(a,d){switch(b.a.u(a)){case "option":switch(typeof d){case "string":b.a.f.set(a,b.c.options.ra,H);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=d;break;default:b.a.f.set(a,b.c.options.ra,d),a.__ko__hasDomDataOptionValue__=l,a.value="number"===typeof d?
+d:""}break;case "select":for(var c=a.options.length-1;0<=c;c--)if(b.k.q(a.options[c])==d){a.selectedIndex=c;break}break;default:if(d===n||d===H)d="";a.value=d}}};b.b("selectExtensions",b.k);b.b("selectExtensions.readValue",b.k.q);b.b("selectExtensions.writeValue",b.k.T);var ja=/\@ko_token_(\d+)\@/g,ma=["true","false"],na=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;b.g={Q:[],aa:function(a){var d=b.a.D(a);if(3>d.length)return[];"{"===d.charAt(0)&&(d=d.substring(1,d.length-1));for(var a=[],
+c=n,e,f=0;f$/:/^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/,ha=J?/^<\!--\s*\/ko\s*--\>$/:
+/^\s*\/ko\s*$/,oa={ul:l,ol:l};b.e={I:{},childNodes:function(a){return A(a)?$(a):a.childNodes},Y:function(a){if(A(a))for(var a=b.e.childNodes(a),d=0,c=a.length;d=b.a.Z&&e in ea?(e=ea[e],g?a.removeAttribute(e):
+a[e]=f):g||a.setAttribute(e,f.toString());"name"===e&&b.a.$a(a,g?"":f.toString())}}};b.c.checked={init:function(a,d,c){b.a.n(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=d(),g=b.a.d(f);"checkbox"==a.type&&g instanceof Array?(e=b.a.i(g,a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):b.g.ea(f,c,"checked",e,l)});"radio"==a.type&&!a.name&&b.c.uniqueName.init(a,t(l))},update:function(a,d){var c=b.a.d(d());
+"checkbox"==a.type?a.checked=c instanceof Array?0<=b.a.i(c,a.value):c:"radio"==a.type&&(a.checked=a.value==c)}};b.c.css={update:function(a,d){var c=b.a.d(d());if("object"==typeof c)for(var e in c){var f=b.a.d(c[e]);b.a.da(a,e,f)}else c=String(c||""),b.a.da(a,a.__ko__cssValue,q),a.__ko__cssValue=c,b.a.da(a,c,l)}};b.c.enable={update:function(a,d){var c=b.a.d(d());c&&a.disabled?a.removeAttribute("disabled"):!c&&!a.disabled&&(a.disabled=l)}};b.c.disable={update:function(a,d){b.c.enable.update(a,function(){return!b.a.d(d())})}};
+b.c.event={init:function(a,d,c,e){var f=d()||{},g;for(g in f)(function(){var f=g;"string"==typeof f&&b.a.n(a,f,function(a){var g,m=d()[f];if(m){var p=c();try{var r=b.a.L(arguments);r.unshift(e);g=m.apply(e,r)}finally{g!==l&&(a.preventDefault?a.preventDefault():a.returnValue=q)}p[f+"Bubble"]===q&&(a.cancelBubble=l,a.stopPropagation&&a.stopPropagation())}})})()}};b.c.foreach={Ra:function(a){return function(){var d=a(),c=b.a.ta(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:b.C.na};
+b.a.d(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:b.C.na}}},init:function(a,d){return b.c.template.init(a,b.c.foreach.Ra(d))},update:function(a,d,c,e,f){return b.c.template.update(a,b.c.foreach.Ra(d),c,e,f)}};b.g.Q.foreach=q;b.e.I.foreach=l;b.c.hasfocus={init:function(a,d,c){function e(e){a.__ko_hasfocusUpdating=l;var f=a.ownerDocument;"activeElement"in
+f&&(e=f.activeElement===a);f=d();b.g.ea(f,c,"hasfocus",e,l);a.__ko_hasfocusUpdating=q}var f=e.bind(n,l),g=e.bind(n,q);b.a.n(a,"focus",f);b.a.n(a,"focusin",f);b.a.n(a,"blur",g);b.a.n(a,"focusout",g)},update:function(a,d){var c=b.a.d(d());a.__ko_hasfocusUpdating||(c?a.focus():a.blur(),b.r.K(b.a.Aa,n,[a,c?"focusin":"focusout"]))}};b.c.html={init:function(){return{controlsDescendantBindings:l}},update:function(a,d){b.a.ca(a,d())}};var ca="__ko_withIfBindingData";P("if");P("ifnot",q,l);P("with",l,q,function(a,
+b){return a.createChildContext(b)});b.c.options={update:function(a,d,c){"select"!==b.a.u(a)&&i(Error("options binding applies only to SELECT elements"));for(var e=0==a.length,f=b.a.V(b.a.fa(a.childNodes,function(a){return a.tagName&&"option"===b.a.u(a)&&a.selected}),function(a){return b.k.q(a)||a.innerText||a.textContent}),g=a.scrollTop,h=b.a.d(d());0/g;b.ya={ub:function(a,
+d,c){d.isTemplateRewritten(a,c)||d.rewriteTemplate(a,function(a){return b.ya.Fb(a,d)},c)},Fb:function(a,b){return a.replace(pa,function(a,e,f,g,h,j,k){return V(k,e,b)}).replace(qa,function(a,e){return V(e,"<\!-- ko --\>",b)})},jb:function(a){return b.s.qa(function(d,c){d.nextSibling&&b.Ea(d.nextSibling,a,c)})}};b.b("__tr_ambtns",b.ya.jb);b.l={};b.l.h=function(a){this.h=a};b.l.h.prototype.text=function(){var a=b.a.u(this.h),a="script"===a?"text":"textarea"===a?"value":"innerHTML";if(0==arguments.length)return this.h[a];
+var d=arguments[0];"innerHTML"===a?b.a.ca(this.h,d):this.h[a]=d};b.l.h.prototype.data=function(a){if(1===arguments.length)return b.a.f.get(this.h,"templateSourceData_"+a);b.a.f.set(this.h,"templateSourceData_"+a,arguments[1])};b.l.O=function(a){this.h=a};b.l.O.prototype=new b.l.h;b.l.O.prototype.text=function(){if(0==arguments.length){var a=b.a.f.get(this.h,"__ko_anon_template__")||{};a.za===H&&a.ia&&(a.za=a.ia.innerHTML);return a.za}b.a.f.set(this.h,"__ko_anon_template__",{za:arguments[0]})};b.l.h.prototype.nodes=
+function(){if(0==arguments.length)return(b.a.f.get(this.h,"__ko_anon_template__")||{}).ia;b.a.f.set(this.h,"__ko_anon_template__",{ia:arguments[0]})};b.b("templateSources",b.l);b.b("templateSources.domElement",b.l.h);b.b("templateSources.anonymousTemplate",b.l.O);var N;b.va=function(a){a!=H&&!(a instanceof b.v)&&i(Error("templateEngine must inherit from ko.templateEngine"));N=a};b.ua=function(a,d,c,e,f){c=c||{};(c.templateEngine||N)==H&&i(Error("Set a template engine before calling renderTemplate"));
+f=f||"replaceChildren";if(e){var g=M(e);return b.j(function(){var h=d&&d instanceof b.z?d:new b.z(b.a.d(d)),j="function"==typeof a?a(h.$data,h):a,h=S(e,f,j,h,c);"replaceNode"==f&&(e=h,g=M(e))},n,{Ja:function(){return!g||!b.a.X(g)},W:g&&"replaceNode"==f?g.parentNode:g})}return b.s.qa(function(e){b.ua(a,d,c,e,"replaceNode")})};b.Lb=function(a,d,c,e,f){function g(a,b){T(b,j);c.afterRender&&c.afterRender(b,a)}function h(d,e){j=f.createChildContext(b.a.d(d),c.as);j.$index=e;var g="function"==typeof a?
+a(d,j):a;return S(n,"ignoreTargetNode",g,j,c)}var j;return b.j(function(){var a=b.a.d(d)||[];"undefined"==typeof a.length&&(a=[a]);a=b.a.fa(a,function(a){return c.includeDestroyed||a===H||a===n||!b.a.d(a._destroy)});b.r.K(b.a.Za,n,[e,a,h,c,g])},n,{W:e})};b.c.template={init:function(a,d){var c=b.a.d(d());if("string"!=typeof c&&!c.name&&(1==a.nodeType||8==a.nodeType))c=1==a.nodeType?a.childNodes:b.e.childNodes(a),c=b.a.Gb(c),(new b.l.O(a)).nodes(c);return{controlsDescendantBindings:l}},update:function(a,
+d,c,e,f){var d=b.a.d(d()),c={},e=l,g,h=n;"string"!=typeof d&&(c=d,d=c.name,"if"in c&&(e=b.a.d(c["if"])),e&&"ifnot"in c&&(e=!b.a.d(c.ifnot)),g=b.a.d(c.data));"foreach"in c?h=b.Lb(d||a,e&&c.foreach||[],c,a,f):e?(f="data"in c?f.createChildContext(g,c.as):f,h=b.ua(d||a,f,c,a)):b.e.Y(a);f=h;(g=b.a.f.get(a,"__ko__templateComputedDomDataKey__"))&&"function"==typeof g.B&&g.B();b.a.f.set(a,"__ko__templateComputedDomDataKey__",f&&f.oa()?f:H)}};b.g.Q.template=function(a){a=b.g.aa(a);return 1==a.length&&a[0].unknown||
+b.g.Db(a,"name")?n:"This template engine does not support anonymous templates nested within its templates"};b.e.I.template=l;b.b("setTemplateEngine",b.va);b.b("renderTemplate",b.ua);b.a.Ia=function(a,b,c){a=a||[];b=b||[];return a.length<=b.length?R(a,b,"added","deleted",c):R(b,a,"deleted","added",c)};b.b("utils.compareArrays",b.a.Ia);b.a.Za=function(a,d,c,e,f){function g(a,b){s=k[b];v!==b&&(y[a]=s);s.ma(v++);L(s.M);r.push(s);z.push(s)}function h(a,c){if(a)for(var d=0,e=c.length;db.a.Z)&&a.nodes?a.nodes():n;if(d)return b.a.L(d.cloneNode(l).childNodes);a=a.text();return b.a.sa(a)};b.C.na=new b.C;b.va(b.C.na);b.b("nativeTemplateEngine",b.C);b.pa=function(){var a=this.Cb=function(){if("undefined"==typeof E||!E.tmpl)return 0;try{if(0<=E.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,c,e){e=e||{};2>a&&i(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));
+var f=b.data("precompiled");f||(f=b.text()||"",f=E.template(n,"{{ko_with $item.koBindingContext}}"+f+"{{/ko_with}}"),b.data("precompiled",f));b=[c.$data];c=E.extend({koBindingContext:c},e.templateOptions);c=E.tmpl(f,b,c);c.appendTo(x.createElement("div"));E.fragments={};return c};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){x.write("");
+ };
+
+ if (jQueryTmplVersion > 0) {
+ jQuery['tmpl']['tag']['ko_code'] = {
+ open: "__.push($1 || '');"
+ };
+ jQuery['tmpl']['tag']['ko_with'] = {
+ open: "with($1) {",
+ close: "} "
+ };
+ }
+ };
+
+ ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
+
+ // Use this one by default *only if jquery.tmpl is referenced*
+ var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
+ if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
+ ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
+
+ ko.exportSymbol('ko.jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
+})();})(window);
diff --git a/EFMVC.Web/Scripts/knockout-2.0.0.js b/EFMVC.Web/Scripts/knockout-2.0.0.js
new file mode 100644
index 0000000..d78d45e
--- /dev/null
+++ b/EFMVC.Web/Scripts/knockout-2.0.0.js
@@ -0,0 +1,129 @@
+/*!
+* Note: While Microsoft is not the author of this script file, Microsoft
+* grants you the right to use this file for the sole purpose of either:
+* (i) interacting through your browser with the Microsoft website, subject
+* to the website's terms of use; or (ii) using the files as included with a
+* Microsoft product subject to the Microsoft Software License Terms for that
+* Microsoft product. Microsoft reserves all other rights to the files not
+* expressly granted by Microsoft, whether by implication, estoppel or
+* otherwise. The notices and licenses below are for informational purposes
+* only.
+*
+* Provided for Informational Purposes Only
+* MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+// Knockout JavaScript library v2.0.0
+// (c) Steven Sanderson - http://knockoutjs.com/
+// License: MIT (http://www.opensource.org/licenses/mit-license.php)
+
+(function(window,undefined){
+function c(a){throw a;}var l=void 0,m=!0,o=null,p=!1,r=window.ko={};r.b=function(a,b){for(var d=a.split("."),e=window,f=0;f ",b[0];);return 4r.a.k(e,a[b])&&e.push(a[b]);return e},ba:function(a,e){for(var a=a||[],b=[],f=0,d=a.length;fa.length?p:a.substring(0,e.length)===e},hb:function(a){for(var e=Array.prototype.slice.call(arguments,1),b="return ("+a+")",f=0;f",""]||!d.indexOf(""," "]||(!d.indexOf(""," "]||[0,"",""];a="ignored"+
+d[1]+a+d[2]+"
";for("function"==typeof window.innerShiv?b.appendChild(window.innerShiv(a)):b.innerHTML=a;d[0]--;)b=b.lastChild;b=r.a.X(b.lastChild.childNodes)}return b};r.a.Z=function(a,b){r.a.U(a);if(b!==o&&b!==l)if("string"!=typeof b&&(b=b.toString()),"undefined"!=typeof jQuery)jQuery(a).html(b);else for(var d=r.a.ma(b),e=0;e"},Ra:function(a,b){var h=d[a];h===l&&c(Error("Couldn't find any memo with ID "+
+a+". Perhaps it's already been unmemoized."));try{return h.apply(o,b||[]),m}finally{delete d[a]}},Sa:function(a,f){var d=[];b(a,d);for(var g=0,i=d.length;gb;b++)a=a();return a})};r.toJSON=function(a){a=r.Pa(a);return r.a.qa(a)}})();r.b("ko.toJS",r.Pa);r.b("ko.toJSON",r.toJSON);
+r.h={q:function(a){return"OPTION"==a.tagName?a.__ko__hasDomDataOptionValue__===m?r.a.e.get(a,r.c.options.la):a.getAttribute("value"):"SELECT"==a.tagName?0<=a.selectedIndex?r.h.q(a.options[a.selectedIndex]):l:a.value},S:function(a,b){if("OPTION"==a.tagName)switch(typeof b){case "string":r.a.e.set(a,r.c.options.la,l);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=b;break;default:r.a.e.set(a,r.c.options.la,b),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof b?
+b:""}else if("SELECT"==a.tagName)for(var d=a.options.length-1;0<=d;d--){if(r.h.q(a.options[d])==b){a.selectedIndex=d;break}}else{if(b===o||b===l)b="";a.value=b}}};r.b("ko.selectExtensions",r.h);r.b("ko.selectExtensions.readValue",r.h.q);r.b("ko.selectExtensions.writeValue",r.h.S);
+r.j=function(){function a(a,e){for(var d=o;a!=d;)d=a,a=a.replace(b,function(a,b){return e[b]});return a}var b=/\@ko_token_(\d+)\@/g,d=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,e=["true","false"];return{D:[],Y:function(b){var e=r.a.z(b);if(3>e.length)return[];"{"===e.charAt(0)&&(e=e.substring(1,e.length-1));for(var b=[],d=o,i,j=0;j$/:
+/^\s*ko\s+(.*\:.*)\s*$/,g=f?/^<\!--\s*\/ko\s*--\>$/:/^\s*\/ko\s*$/,i={ul:m,ol:m};r.f={C:{},childNodes:function(b){return a(b)?d(b):b.childNodes},ha:function(b){if(a(b))for(var b=r.f.childNodes(b),e=0,d=b.length;e "),p)}};r.c.uniqueName.Za=0;
+r.c.checked={init:function(a,b,d){r.a.s(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=b();"checkbox"==a.type&&r.a.d(f)instanceof Array?(e=r.a.k(r.a.d(f),a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):r.P(f)?f()!==e&&f(e):(f=d(),f._ko_property_writers&&f._ko_property_writers.checked&&f._ko_property_writers.checked(e))});"radio"==a.type&&!a.name&&r.c.uniqueName.init(a,function(){return m})},update:function(a,
+b){var d=r.a.d(b());if("checkbox"==a.type)a.checked=d instanceof Array?0<=r.a.k(d,a.value):d;else if("radio"==a.type)a.checked=a.value==d}};r.c.attr={update:function(a,b){var d=r.a.d(b())||{},e;for(e in d)if("string"==typeof e){var f=r.a.d(d[e]);f===p||f===o||f===l?a.removeAttribute(e):a.setAttribute(e,f.toString())}}};
+r.c.hasfocus={init:function(a,b,d){function e(a){var e=b();a!=r.a.d(e)&&(r.P(e)?e(a):(e=d(),e._ko_property_writers&&e._ko_property_writers.hasfocus&&e._ko_property_writers.hasfocus(a)))}r.a.s(a,"focus",function(){e(m)});r.a.s(a,"focusin",function(){e(m)});r.a.s(a,"blur",function(){e(p)});r.a.s(a,"focusout",function(){e(p)})},update:function(a,b){var d=r.a.d(b());d?a.focus():a.blur();r.a.sa(a,d?"focusin":"focusout")}};
+r.c["with"]={o:function(a){return function(){var b=a();return{"if":b,data:b,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["with"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["with"].o(b),d,e,f)}};r.j.D["with"]=p;r.f.C["with"]=m;r.c["if"]={o:function(a){return function(){return{"if":a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["if"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["if"].o(b),d,e,f)}};
+r.j.D["if"]=p;r.f.C["if"]=m;r.c.ifnot={o:function(a){return function(){return{ifnot:a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.ifnot.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.ifnot.o(b),d,e,f)}};r.j.D.ifnot=p;r.f.C.ifnot=m;
+r.c.foreach={o:function(a){return function(){var b=r.a.d(a());return!b||"number"==typeof b.length?{foreach:b,templateEngine:r.p.M}:{foreach:b.data,includeDestroyed:b.includeDestroyed,afterAdd:b.afterAdd,beforeRemove:b.beforeRemove,afterRender:b.afterRender,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.foreach.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.foreach.o(b),d,e,f)}};r.j.D.foreach=p;r.f.C.foreach=m;r.b("ko.allowedVirtualElementBindings",r.f.C);
+r.t=function(){};r.t.prototype.renderTemplateSource=function(){c("Override renderTemplateSource")};r.t.prototype.createJavaScriptEvaluatorBlock=function(){c("Override createJavaScriptEvaluatorBlock")};r.t.prototype.makeTemplateSource=function(a){if("string"==typeof a){var b=document.getElementById(a);b||c(Error("Cannot find template with ID "+a));return new r.m.g(b)}if(1==a.nodeType||8==a.nodeType)return new r.m.I(a);c(Error("Unknown template type: "+a))};
+r.t.prototype.renderTemplate=function(a,b,d){return this.renderTemplateSource(this.makeTemplateSource(a),b,d)};r.t.prototype.isTemplateRewritten=function(a){return this.allowTemplateRewriting===p?m:this.W&&this.W[a]?m:this.makeTemplateSource(a).data("isRewritten")};r.t.prototype.rewriteTemplate=function(a,b){var d=this.makeTemplateSource(a),e=b(d.text());d.text(e);d.data("isRewritten",m);if("string"==typeof a)this.W=this.W||{},this.W[a]=m};r.b("ko.templateEngine",r.t);
+r.$=function(){function a(a,b,d){for(var a=r.j.Y(a),g=r.j.D,i=0;i/g;return{gb:function(a,b){b.isTemplateRewritten(a)||b.rewriteTemplate(a,function(a){return r.$.ub(a,b)})},ub:function(e,f){return e.replace(b,function(b,e,d,j,k,n,t){return a(t,e,f)}).replace(d,function(b,e){return a(e,"<\!-- ko --\>",f)})},Ua:function(a){return r.r.ka(function(b,d){b.nextSibling&&r.xa(b.nextSibling,a,d)})}}}();r.b("ko.templateRewriting",r.$);r.b("ko.templateRewriting.applyMemoizedBindingsToNextSibling",r.$.Ua);r.m={};r.m.g=function(a){this.g=a};
+r.m.g.prototype.text=function(){if(0==arguments.length)return"script"==this.g.tagName.toLowerCase()?this.g.text:this.g.innerHTML;var a=arguments[0];"script"==this.g.tagName.toLowerCase()?this.g.text=a:r.a.Z(this.g,a)};r.m.g.prototype.data=function(a){if(1===arguments.length)return r.a.e.get(this.g,"templateSourceData_"+a);r.a.e.set(this.g,"templateSourceData_"+a,arguments[1])};r.m.I=function(a){this.g=a};r.m.I.prototype=new r.m.g;
+r.m.I.prototype.text=function(){if(0==arguments.length)return r.a.e.get(this.g,"__ko_anon_template__");r.a.e.set(this.g,"__ko_anon_template__",arguments[0])};r.b("ko.templateSources",r.m);r.b("ko.templateSources.domElement",r.m.g);r.b("ko.templateSources.anonymousTemplate",r.m.I);
+(function(){function a(a,b,d){for(var g=0;node=a[g];g++)node.parentNode===b&&(1===node.nodeType||8===node.nodeType)&&d(node)}function b(a,b,h,g,i){var i=i||{},j=i.templateEngine||d;r.$.gb(h,j);h=j.renderTemplate(h,g,i);("number"!=typeof h.length||0a&&c(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));var h=d.data("precompiled");h||(h=d.text()||"",h=jQuery.template(o,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),d.data("precompiled",h));
+d=[e.$data];e=jQuery.extend({koBindingContext:e},f.templateOptions);e=jQuery.tmpl(h,d,e);e.appendTo(document.createElement("div"));jQuery.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){document.write("
diff --git a/MyFinance.Web/Views/Account/ChangePasswordSuccess.cshtml b/EFMVC.Web/Views/Account/ChangePasswordSuccess.cshtml
similarity index 100%
rename from MyFinance.Web/Views/Account/ChangePasswordSuccess.cshtml
rename to EFMVC.Web/Views/Account/ChangePasswordSuccess.cshtml
diff --git a/MyFinance.Web/Views/Account/LogOn.cshtml b/EFMVC.Web/Views/Account/LogOn.cshtml
similarity index 88%
rename from MyFinance.Web/Views/Account/LogOn.cshtml
rename to EFMVC.Web/Views/Account/LogOn.cshtml
index 6a58049..3901d7e 100644
--- a/MyFinance.Web/Views/Account/LogOn.cshtml
+++ b/EFMVC.Web/Views/Account/LogOn.cshtml
@@ -1,4 +1,4 @@
-@model MyFinance.Web.Models.LogOnModel
+@model EFMVC.Web.ViewModels.LogOnFormModel
@{
ViewBag.Title = "Log On";
@@ -6,7 +6,7 @@
Log On
- Please enter your username and password. @Html.ActionLink("Register", "Register") if you don't have an account.
+ Please enter your user name and password. @Html.ActionLink("Register", "Register") if you don't have an account.
diff --git a/EFMVC.Web/Views/Account/Login.cshtml b/EFMVC.Web/Views/Account/Login.cshtml
new file mode 100644
index 0000000..282fa8e
--- /dev/null
+++ b/EFMVC.Web/Views/Account/Login.cshtml
@@ -0,0 +1,41 @@
+@model EFMVC.Web.ViewModels.LogOnFormModel
+
+@{
+ ViewBag.Title = "Log in";
+}
+
+
+ @ViewBag.Title.
+ Enter your user name and password below.
+
+
+
+
+
+@using (Html.BeginForm((string)ViewBag.FormAction, "Account")) {
+ @Html.ValidationSummary(true, "Log in was unsuccessful. Please correct the errors and try again.")
+
+
+ Log in Form
+
+
+ @Html.LabelFor(m => m.UserName)
+ @Html.TextBoxFor(m => m.UserName)
+ @Html.ValidationMessageFor(m => m.UserName)
+
+
+ @Html.LabelFor(m => m.Password)
+ @Html.PasswordFor(m => m.Password)
+ @Html.ValidationMessageFor(m => m.Password)
+
+
+ @Html.CheckBoxFor(m => m.RememberMe)
+ @Html.LabelFor(m => m.RememberMe, new { @class = "checkbox" })
+
+
+
+
+
+ @Html.ActionLink("Register", "Register") if you don't have an account.
+
+}
diff --git a/MyFinance.Web/Views/Account/Register.cshtml b/EFMVC.Web/Views/Account/Register.cshtml
similarity index 72%
rename from MyFinance.Web/Views/Account/Register.cshtml
rename to EFMVC.Web/Views/Account/Register.cshtml
index a1429b7..e28347f 100644
--- a/MyFinance.Web/Views/Account/Register.cshtml
+++ b/EFMVC.Web/Views/Account/Register.cshtml
@@ -1,4 +1,4 @@
-@model MyFinance.Web.Models.RegisterModel
+@model EFMVC.Web.ViewModels.UserFormModel
@{
ViewBag.Title = "Register";
@@ -9,34 +9,41 @@
Use the form below to create a new account.
- Passwords are required to be a minimum of @ViewBag.PasswordLength characters in length.
+ Passwords are required to be a minimum of 6 characters in length.
-@using (Html.BeginForm()) {
+@using (Html.BeginForm((string)ViewBag.FormAction, "Account")) {
@Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.")
Account Information
-
- @Html.LabelFor(m => m.UserName)
+
+ @Html.LabelFor(m => m.Email)
- @Html.TextBoxFor(m => m.UserName)
- @Html.ValidationMessageFor(m => m.UserName)
+ @Html.TextBoxFor(m => m.Email)
+ @Html.ValidationMessageFor(m => m.Email)
- @Html.LabelFor(m => m.Email)
+ @Html.LabelFor(m => m.FirstName)
- @Html.TextBoxFor(m => m.Email)
- @Html.ValidationMessageFor(m => m.Email)
+ @Html.TextBoxFor(m => m.FirstName)
+ @Html.ValidationMessageFor(m => m.FirstName)
+
+ @Html.LabelFor(m => m.LastName)
+
+
+ @Html.TextBoxFor(m => m.LastName)
+ @Html.ValidationMessageFor(m => m.LastName)
+
@Html.LabelFor(m => m.Password)
diff --git a/EFMVC.Web/Views/Category/Create.cshtml b/EFMVC.Web/Views/Category/Create.cshtml
new file mode 100644
index 0000000..60569a6
--- /dev/null
+++ b/EFMVC.Web/Views/Category/Create.cshtml
@@ -0,0 +1,23 @@
+@model EFMVC.Web.ViewModels.CategoryFormModel
+ @{
+ ViewBag.Title = "Create";
+}
+
Create
+@using (Html.BeginForm("Save", "Category"))
+{
+ @Html.AntiForgeryToken()
+ @Html.ValidationSummary(true)
+
+ Category
+
+ @Html.Partial("_CreateOrEdit", Model)
+
+
+
+
+
+}
+
+
+ @Html.ActionLink("Back to List", "Index")
+
diff --git a/EFMVC.Web/Views/Category/Edit.cshtml b/EFMVC.Web/Views/Category/Edit.cshtml
new file mode 100644
index 0000000..8e71daa
--- /dev/null
+++ b/EFMVC.Web/Views/Category/Edit.cshtml
@@ -0,0 +1,24 @@
+@model EFMVC.Web.ViewModels.CategoryFormModel
+@{
+ ViewBag.Title = "Edit";
+}
+
Edit
+@using (Html.BeginForm("Save", "Category"))
+{
+ @Html.AntiForgeryToken()
+ @Html.ValidationSummary(true)
+
+ Category
+
+ @Html.HiddenFor(model => model.CategoryId)
+ @Html.Partial("_CreateOrEdit", Model)
+
+
+
+
+
+}
+
+
+ @Html.ActionLink("Back to List", "Index")
+
diff --git a/EFMVC.Web/Views/Category/Index.cshtml b/EFMVC.Web/Views/Category/Index.cshtml
new file mode 100644
index 0000000..26e35d3
--- /dev/null
+++ b/EFMVC.Web/Views/Category/Index.cshtml
@@ -0,0 +1,10 @@
+@model IEnumerable
+
+@{
+ ViewBag.Title = "Index";
+}
+
+Category List
+
+ @Html.Partial("_CategoryList", Model)
+
\ No newline at end of file
diff --git a/MyFinance.Web/Views/Category/CategoryList.cshtml b/EFMVC.Web/Views/Category/_CategoryList.cshtml
similarity index 67%
rename from MyFinance.Web/Views/Category/CategoryList.cshtml
rename to EFMVC.Web/Views/Category/_CategoryList.cshtml
index f41e3e7..f9997c4 100644
--- a/MyFinance.Web/Views/Category/CategoryList.cshtml
+++ b/EFMVC.Web/Views/Category/_CategoryList.cshtml
@@ -1,8 +1,10 @@
-@using MyFinance.Helpers;
-@using MyFinance.Domain;
-@model IEnumerable
-
-
+@model IEnumerable
+
+
+ @Html.ActionLink("Create New", "Create")
+
+
+
Actions
Name
Description
@@ -12,7 +14,7 @@
@Html.ActionLink("Edit", "Edit",new { id = item.CategoryId })
@Ajax.ActionLink("Delete", "Delete", new { id = item.CategoryId },
- new AjaxOptions { Confirm = "Delete Expense?", HttpMethod = "Post",
+ new AjaxOptions { Confirm = "Delete Category?", HttpMethod = "Post",
UpdateTargetId = "divCategoryList" })
@@ -24,8 +26,4 @@
}
-
-
-
- @Html.ActionLink("Create New", "Create")
-
+
diff --git a/EFMVC.Web/Views/Category/_CreateOrEdit.cshtml b/EFMVC.Web/Views/Category/_CreateOrEdit.cshtml
new file mode 100644
index 0000000..02e9d52
--- /dev/null
+++ b/EFMVC.Web/Views/Category/_CreateOrEdit.cshtml
@@ -0,0 +1,20 @@
+@model EFMVC.Web.ViewModels.CategoryFormModel
+@*
+
+*@
+
+
+ @Html.LabelFor(model => model.Name)
+
+
+ @Html.EditorFor(model => model.Name)
+ @Html.ValidationMessageFor(model => model.Name)
+
+
+
+ @Html.LabelFor(model => model.Description)
+
+
+ @Html.EditorFor(model => model.Description)
+ @Html.ValidationMessageFor(model => model.Description)
+
\ No newline at end of file
diff --git a/MyFinance.Web/Views/Expense/Create.cshtml b/EFMVC.Web/Views/Expense/Create.cshtml
similarity index 53%
rename from MyFinance.Web/Views/Expense/Create.cshtml
rename to EFMVC.Web/Views/Expense/Create.cshtml
index 1f4a9e5..2f7c8aa 100644
--- a/MyFinance.Web/Views/Expense/Create.cshtml
+++ b/EFMVC.Web/Views/Expense/Create.cshtml
@@ -1,4 +1,4 @@
-@model MyFinance.Web.ViewModel.ExpenseViewModel
+@model EFMVC.Web.ViewModels.ExpenseFormModel
@{
ViewBag.Title = "Create";
@@ -6,14 +6,15 @@
Create
-
-
+@*
+*@
-@using (Html.BeginForm()) {
+@using (Html.BeginForm("Save","Expense")) {
+ @Html.AntiForgeryToken()
@Html.ValidationSummary(true)
Expense
- @Html.EditorFor(model => model)
+ @Html.Partial("_CreateOrEdit",Model)
diff --git a/MyFinance.Web/Views/Expense/Edit.cshtml b/EFMVC.Web/Views/Expense/Edit.cshtml
similarity index 76%
rename from MyFinance.Web/Views/Expense/Edit.cshtml
rename to EFMVC.Web/Views/Expense/Edit.cshtml
index 7085224..a4d4cd3 100644
--- a/MyFinance.Web/Views/Expense/Edit.cshtml
+++ b/EFMVC.Web/Views/Expense/Edit.cshtml
@@ -1,4 +1,4 @@
-@model MyFinance.Web.ViewModel.ExpenseViewModel
+@model EFMVC.Web.ViewModels.ExpenseFormModel
@{
ViewBag.Title = "Edit";
@@ -9,15 +9,14 @@
-@using (Html.BeginForm()) {
+@using (Html.BeginForm("Save", "Expense"))
+{
+ @Html.AntiForgeryToken()
@Html.ValidationSummary(true)
Expense
-
@Html.HiddenFor(model => model.ExpenseId)
- @Html.EditorFor(model => model)
-
-
+ @Html.Partial("_CreateOrEdit",Model)
diff --git a/MyFinance.Web/Views/Expense/Index.cshtml b/EFMVC.Web/Views/Expense/Index.cshtml
similarity index 66%
rename from MyFinance.Web/Views/Expense/Index.cshtml
rename to EFMVC.Web/Views/Expense/Index.cshtml
index 01093ce..c909f86 100644
--- a/MyFinance.Web/Views/Expense/Index.cshtml
+++ b/EFMVC.Web/Views/Expense/Index.cshtml
@@ -1,13 +1,13 @@
-@using MyFinance.Helpers;
-@model IEnumerable
+@using EFMVC.Web.Helpers;
+@model IEnumerable
@{
ViewBag.Title = "Index";
}
Expense List
-
-
-
-
+@*
+
+
+ *@
@using (Ajax.BeginForm(new AjaxOptions{ UpdateTargetId="divExpenseList", HttpMethod="Get"})) {
}
- @Html.Partial("ExpenseList", Model)
+ @Html.Partial("_ExpenseList", Model)
+@model EFMVC.Web.ViewModels.ExpenseFormModel
+@*
-
+ *@
@@ -16,7 +16,7 @@
@Html.LabelFor(model => model.Date)
- @Html.TextBox("Date", Html.Encode(String.Format("{0:mm/dd/yyyy}", Model.Date.ToShortDateString())), new { @class = "ui-datepicker" })
+ @Html.TextBox("Date", Html.Encode(String.Format("{0:mm/dd/yyyy}", Model.Date.ToShortDateString())), new { @class = "ui-datepicker" })
@Html.ValidationMessageFor(model => model.Date)
@@ -32,7 +32,7 @@
@Html.LabelFor(model => model.CategoryId)
- @Html.DropDownListFor(model => model.CategoryId , Model.Category)
+ @Html.DropDownListFor(model => model.CategoryId , Model.Category,"--Select--")
@Html.ValidationMessageFor(model => model.CategoryId)
-
+
\ No newline at end of file
diff --git a/MyFinance.Web/Views/Expense/ExpenseList.cshtml b/EFMVC.Web/Views/Expense/_ExpenseList.cshtml
similarity index 95%
rename from MyFinance.Web/Views/Expense/ExpenseList.cshtml
rename to EFMVC.Web/Views/Expense/_ExpenseList.cshtml
index 2d4e2d7..647fe2a 100644
--- a/MyFinance.Web/Views/Expense/ExpenseList.cshtml
+++ b/EFMVC.Web/Views/Expense/_ExpenseList.cshtml
@@ -1,4 +1,4 @@
-@model IEnumerable
+@model IEnumerable
diff --git a/MyFinance.Web/Views/Home/About.cshtml b/EFMVC.Web/Views/Home/About.cshtml
similarity index 100%
rename from MyFinance.Web/Views/Home/About.cshtml
rename to EFMVC.Web/Views/Home/About.cshtml
diff --git a/EFMVC.Web/Views/Home/Contact.cshtml b/EFMVC.Web/Views/Home/Contact.cshtml
new file mode 100644
index 0000000..157a73d
--- /dev/null
+++ b/EFMVC.Web/Views/Home/Contact.cshtml
@@ -0,0 +1,50 @@
+@{
+ ViewBag.Title = "Contact";
+}
+
+
+ @ViewBag.Title.
+ @ViewBag.Message
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web/Views/Home/Index.cshtml b/EFMVC.Web/Views/Home/Index.cshtml
new file mode 100644
index 0000000..0a7f6f0
--- /dev/null
+++ b/EFMVC.Web/Views/Home/Index.cshtml
@@ -0,0 +1,11 @@
+@{
+ ViewBag.Title = "Home Page";
+}
+
+@ViewBag.Message
+
+Demo web app using ASP.NET MVC 4, EF Code First, Autofac and Windows Azure
+
+
+
+
diff --git a/EFMVC.Web/Views/Shared/Error.cshtml b/EFMVC.Web/Views/Shared/Error.cshtml
new file mode 100644
index 0000000..db7c8b8
--- /dev/null
+++ b/EFMVC.Web/Views/Shared/Error.cshtml
@@ -0,0 +1,10 @@
+@model System.Web.Mvc.HandleErrorInfo
+
+@{
+ ViewBag.Title = "Error";
+}
+
+
+ Error.
+ An error occurred while processing your request.
+
diff --git a/EFMVC.Web/Views/Shared/_Layout.cshtml b/EFMVC.Web/Views/Shared/_Layout.cshtml
new file mode 100644
index 0000000..4943b96
--- /dev/null
+++ b/EFMVC.Web/Views/Shared/_Layout.cshtml
@@ -0,0 +1,53 @@
+
+
+
+
+ @ViewBag.Title - EFMVC Application
+
+
+
+
+
+
+
+
+
+ @RenderSection("featured", required: false)
+
+
+
+
+
diff --git a/MyFinance.Web/Views/Shared/_LogOnPartial.cshtml b/EFMVC.Web/Views/Shared/_LogOnPartial.cshtml
similarity index 74%
rename from MyFinance.Web/Views/Shared/_LogOnPartial.cshtml
rename to EFMVC.Web/Views/Shared/_LogOnPartial.cshtml
index 8ab1fc1..46a8544 100644
--- a/MyFinance.Web/Views/Shared/_LogOnPartial.cshtml
+++ b/EFMVC.Web/Views/Shared/_LogOnPartial.cshtml
@@ -1,5 +1,5 @@
@if(Request.IsAuthenticated) {
- Welcome @Context.User.Identity.Name !
+ Welcome @User.Identity.Name !
[ @Html.ActionLink("Log Off", "LogOff", "Account") ]
}
else {
diff --git a/EFMVC.Web/Views/Shared/_LoginPartial.cshtml b/EFMVC.Web/Views/Shared/_LoginPartial.cshtml
new file mode 100644
index 0000000..09027f7
--- /dev/null
+++ b/EFMVC.Web/Views/Shared/_LoginPartial.cshtml
@@ -0,0 +1,11 @@
+@if (Request.IsAuthenticated) {
+
+ Hello, @Html.ActionLink(User.Identity.Name, "ChangePassword", "Account", routeValues: null, htmlAttributes: new { @class = "username", title = "Change password" })!
+ @Html.ActionLink("Log off", "LogOff", "Account")
+
+} else {
+
+ @Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink", data_dialog_title = "Registration" })
+ @Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink", data_dialog_title = "Identification" })
+
+}
\ No newline at end of file
diff --git a/MyFinance.Web/Views/Web.config b/EFMVC.Web/Views/Web.config
similarity index 81%
rename from MyFinance.Web/Views/Web.config
rename to EFMVC.Web/Views/Web.config
index a4def2a..826ce19 100644
--- a/MyFinance.Web/Views/Web.config
+++ b/EFMVC.Web/Views/Web.config
@@ -2,14 +2,14 @@
-
-
-
+
+
+
-
+
@@ -38,11 +38,11 @@
-->
+ pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
+ pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
+ userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
-
+
diff --git a/EFMVC.Web/Views/_ViewStart.cshtml b/EFMVC.Web/Views/_ViewStart.cshtml
new file mode 100644
index 0000000..efda124
--- /dev/null
+++ b/EFMVC.Web/Views/_ViewStart.cshtml
@@ -0,0 +1,3 @@
+@{
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
\ No newline at end of file
diff --git a/EFMVC.Web/Web.Debug.config b/EFMVC.Web/Web.Debug.config
new file mode 100644
index 0000000..3e2a97c
--- /dev/null
+++ b/EFMVC.Web/Web.Debug.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web/Web.Release.config b/EFMVC.Web/Web.Release.config
new file mode 100644
index 0000000..9fd481f
--- /dev/null
+++ b/EFMVC.Web/Web.Release.config
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web/Web.config b/EFMVC.Web/Web.config
new file mode 100644
index 0000000..4bb4cb8
--- /dev/null
+++ b/EFMVC.Web/Web.config
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.Web/favicon.ico b/EFMVC.Web/favicon.ico
new file mode 100644
index 0000000..a3a7999
Binary files /dev/null and b/EFMVC.Web/favicon.ico differ
diff --git a/EFMVC.Web/packages.config b/EFMVC.Web/packages.config
new file mode 100644
index 0000000..12cf941
--- /dev/null
+++ b/EFMVC.Web/packages.config
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EFMVC.sln b/EFMVC.sln
new file mode 100644
index 0000000..be0a2e3
--- /dev/null
+++ b/EFMVC.sln
@@ -0,0 +1,77 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Core", "EFMVC.Core\EFMVC.Core.csproj", "{C73D0DF7-D21B-4E15-A8AA-70540236D452}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Model", "EFMVC.Model\EFMVC.Model.csproj", "{0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Data", "EFMVC.Data\EFMVC.Data.csproj", "{6A4C3B88-230D-4C19-945E-4685876AA31D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Tests", "EFMVC.Tests\EFMVC.Tests.csproj", "{4A9546B5-60F4-4442-AD76-5486FB91D6CC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.CommandProcessor", "EFMVC.CommandProcessor\EFMVC.CommandProcessor.csproj", "{955FD94A-BBC1-4469-889A-740FB98338DE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Domain", "EFMVC.Domain\EFMVC.Domain.csproj", "{5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Web.Core", "EFMVC.Web.Core\EFMVC.Web.Core.csproj", "{DBF57927-89DB-4526-A8E0-5C5AC90096B1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Web", "EFMVC.Web\EFMVC.Web.csproj", "{169AFE38-1CA2-4624-BDC4-78C6653B04BD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFMVC.Web.API", "EFMVC.Web.API\EFMVC.Web.API.csproj", "{8739F83B-A769-4FB8-A5B5-D96D640DB716}"
+EndProject
+Project("{CC5FD16D-436D-48AD-A40C-5A424C6E3E79}") = "EFMVC.Azure", "EFMVC.Azure\EFMVC.Azure.ccproj", "{3ECE0219-C411-432F-8013-0B7B69F9F8FC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C73D0DF7-D21B-4E15-A8AA-70540236D452}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CB7B2DB-AECA-421A-AA9F-BFF8B532D535}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6A4C3B88-230D-4C19-945E-4685876AA31D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4A9546B5-60F4-4442-AD76-5486FB91D6CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A9546B5-60F4-4442-AD76-5486FB91D6CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4A9546B5-60F4-4442-AD76-5486FB91D6CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4A9546B5-60F4-4442-AD76-5486FB91D6CC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {955FD94A-BBC1-4469-889A-740FB98338DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {955FD94A-BBC1-4469-889A-740FB98338DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {955FD94A-BBC1-4469-889A-740FB98338DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {955FD94A-BBC1-4469-889A-740FB98338DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5AA95E73-CBDD-460E-96F9-4A3DA709DFE0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DBF57927-89DB-4526-A8E0-5C5AC90096B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DBF57927-89DB-4526-A8E0-5C5AC90096B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DBF57927-89DB-4526-A8E0-5C5AC90096B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DBF57927-89DB-4526-A8E0-5C5AC90096B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {169AFE38-1CA2-4624-BDC4-78C6653B04BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {169AFE38-1CA2-4624-BDC4-78C6653B04BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {169AFE38-1CA2-4624-BDC4-78C6653B04BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {169AFE38-1CA2-4624-BDC4-78C6653B04BD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8739F83B-A769-4FB8-A5B5-D96D640DB716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8739F83B-A769-4FB8-A5B5-D96D640DB716}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8739F83B-A769-4FB8-A5B5-D96D640DB716}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8739F83B-A769-4FB8-A5B5-D96D640DB716}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3ECE0219-C411-432F-8013-0B7B69F9F8FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3ECE0219-C411-432F-8013-0B7B69F9F8FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3ECE0219-C411-432F-8013-0B7B69F9F8FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3ECE0219-C411-432F-8013-0B7B69F9F8FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35
+ EndGlobalSection
+EndGlobal
diff --git a/MyFinance.Data/MyFinanceContext.cs b/MyFinance.Data/MyFinanceContext.cs
deleted file mode 100644
index cf4aeff..0000000
--- a/MyFinance.Data/MyFinanceContext.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Data.Entity;
-using MyFinance.Domain;
-namespace MyFinance.Data
-{
- public class MyFinanceContext : DbContext
- {
- // public MyFinanceContext() : base("MyFinance") { }
- public DbSet Categories { get; set; }
- public DbSet Expenses { get; set; }
- public DbSet Users { get; set; }
- public DbSet Roles { get; set; }
- public virtual void Commit()
- {
- base.SaveChanges();
- }
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- modelBuilder.Entity()
- .HasMany(u => u.Roles)
- .WithMany(r => r.Users)
- .Map(m =>
- {
- m.ToTable("RoleMemberships");
- m.MapLeftKey("UserName");
- m.MapRightKey("RoleName");
- });
- }
- }
-
- public class MyFinanceContextInitializer : DropCreateDatabaseIfModelChanges
- {
- protected override void Seed(MyFinanceContext context)
- {
- var roles = new List{
- new Role{RoleName = "Administrator"},
- new Role{RoleName = "User"}
- };
-
- roles.ForEach(r => context.Roles.Add(r));
- }
- }
-}
diff --git a/MyFinance.Data/Repositories/CategoryRepository.cs b/MyFinance.Data/Repositories/CategoryRepository.cs
deleted file mode 100644
index 1fbb4f1..0000000
--- a/MyFinance.Data/Repositories/CategoryRepository.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
-namespace MyFinance.Data
-{
- public class CategoryRepository: RepositoryBase, ICategoryRepository
- {
- public CategoryRepository(IDatabaseFactory databaseFactory)
- : base(databaseFactory)
- {
- }
- }
- public interface ICategoryRepository : IRepository
- {
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Data/Repositories/RoleRepository.cs b/MyFinance.Data/Repositories/RoleRepository.cs
deleted file mode 100644
index 947a4a3..0000000
--- a/MyFinance.Data/Repositories/RoleRepository.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
-
-namespace MyFinance.Data
-{
- public class RoleRepository : RepositoryBase, IRoleRepository
- {
- public RoleRepository(IDatabaseFactory databaseFactory)
- : base(databaseFactory)
- {
- }
-
- }
- public interface IRoleRepository : IRepository
- {
-
- }
-}
diff --git a/MyFinance.Data/Repositories/UserRepository.cs b/MyFinance.Data/Repositories/UserRepository.cs
deleted file mode 100644
index 801636f..0000000
--- a/MyFinance.Data/Repositories/UserRepository.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
-using System.Data;
-
-namespace MyFinance.Data
-{
- public class UserRepository : RepositoryBase, IUserRepository
- {
- public UserRepository(IDatabaseFactory databaseFactory)
- : base(databaseFactory)
- {
- }
- public void AssignRole(string userName, List roleNames)
- {
- var user = this.GetById(userName);
- user.Roles.Clear();
- foreach (string roleName in roleNames)
- {
- var role = this.DataContext.Roles.Find(roleName);
- user.Roles.Add(role);
- }
-
- this.DataContext.Users.Attach(user);
- this.DataContext.Entry(user).State = EntityState.Modified;
- }
-
- }
-
- public interface IUserRepository : IRepository
- {
- void AssignRole(string userName, List roleName);
- }
-}
diff --git a/MyFinance.Domain/Entities/Category.cs b/MyFinance.Domain/Entities/Category.cs
deleted file mode 100644
index c4a7141..0000000
--- a/MyFinance.Domain/Entities/Category.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.ComponentModel.DataAnnotations;
-
-namespace MyFinance.Domain
-{
- public class Category
- {
-
- public int CategoryId { get; set; }
-
- [Required(ErrorMessage = "Name Required")]
- [StringLength(25, ErrorMessage = "Must be less than 25 characters")]
- [MaxLength(50)]
- public string Name { get; set;}
- public string Description { get; set; }
- public virtual ICollection Expenses { get; set; }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Domain/Entities/Expense.cs b/MyFinance.Domain/Entities/Expense.cs
deleted file mode 100644
index eb8ebfc..0000000
--- a/MyFinance.Domain/Entities/Expense.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.ComponentModel.DataAnnotations;
-namespace MyFinance.Domain
-{
- public class Expense
- {
-
- public int ExpenseId { get; set; }
- [Required]
- [MaxLength(100)]
- public string Transaction { get; set; }
- [Required]
- public DateTime Date { get; set; }
- [Required]
- public double Amount { get; set; }
- [Required]
- public int CategoryId { get; set; }
- public virtual Category Category { get; set; }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Domain/Entities/Role.cs b/MyFinance.Domain/Entities/Role.cs
deleted file mode 100644
index 944bdb3..0000000
--- a/MyFinance.Domain/Entities/Role.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.ComponentModel.DataAnnotations;
-
-namespace MyFinance.Domain
-{
- public class Role
- {
- [Key]
- [Display(Name = "Role Name")]
- [Required]
- [MaxLength(100)]
- public string RoleName { get; set; }
- public virtual ICollection Users { get; set; }
- }
-}
diff --git a/MyFinance.Domain/Entities/User.cs b/MyFinance.Domain/Entities/User.cs
deleted file mode 100644
index ab9bef7..0000000
--- a/MyFinance.Domain/Entities/User.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.ComponentModel.DataAnnotations;
-
-namespace MyFinance.Domain
-{
- public class User
- {
- [Key]
- [Required]
- [Display(Name = "User Name")]
- [MaxLength(100)]
- public string UserName { get; set; }
-
- [Required]
- [MaxLength(64)]
- public byte[] PasswordHash { get; set; }
-
- [Required]
- [MaxLength(128)]
- public byte[] PasswordSalt { get; set; }
-
- [Required(ErrorMessage = "Email is required")]
- [MaxLength(200)]
- public string Email { get; set; }
-
- [MaxLength(200)]
- public string Comment { get; set; }
-
- [Display(Name = "Approved?")]
- public bool IsApproved { get; set; }
-
- [Display(Name = "Crate Date")]
- public DateTime DateCreated { get; set; }
-
- [Display(Name = "Last Login Date")]
- public DateTime? DateLastLogin { get; set; }
-
- [Display(Name = "Last Activity Date")]
- public DateTime? DateLastActivity { get; set; }
-
- [Display(Name = "Last Password Change Date")]
- public DateTime DateLastPasswordChange { get; set; }
-
- public virtual ICollection Roles { get; set; }
-
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Service/CategoryService.cs b/MyFinance.Service/CategoryService.cs
deleted file mode 100644
index 51d4840..0000000
--- a/MyFinance.Service/CategoryService.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data;
-using MyFinance.Data.Infrastructure;
-
-namespace MyFinance.Service
-{
- public interface ICategoryService
- {
- IEnumerable GetCategories();
- Category GetCategory(int id);
- void CreateCategory(Category category);
- void DeleteCategory(int id);
- void SaveCategory();
- }
- public class CategoryService : ICategoryService
- {
- private readonly ICategoryRepository categoryRepository;
- private readonly IUnitOfWork unitOfWork;
- public CategoryService(ICategoryRepository categoryRepository, IUnitOfWork unitOfWork)
- {
- this.categoryRepository = categoryRepository;
- this.unitOfWork = unitOfWork;
- }
- #region ICategoryService Members
-
- public IEnumerable GetCategories()
- {
- var categories = categoryRepository.GetAll();
- return categories;
- }
-
- public Category GetCategory(int id)
- {
- var category = categoryRepository.GetById(id);
- return category;
- }
-
- public void CreateCategory(Category category)
- {
- categoryRepository.Add(category);
- SaveCategory();
- }
-
- public void DeleteCategory(int id)
- {
- var category = categoryRepository.GetById(id);
- categoryRepository.Delete(category);
- SaveCategory();
- }
-
- public void SaveCategory()
- {
- unitOfWork.Commit();
- }
-
- #endregion
- }
-}
diff --git a/MyFinance.Service/ExpenseService.cs b/MyFinance.Service/ExpenseService.cs
deleted file mode 100644
index c1d683e..0000000
--- a/MyFinance.Service/ExpenseService.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Data;
-
-namespace MyFinance.Service
-{
- public interface IExpenseService
- {
- IEnumerable GetExpenses(DateTime startDate, DateTime ednDate);
- Expense GetExpense(int id);
- void CreateExpense(Expense expense);
- void DeleteExpense(int id);
- void SaveExpense();
- }
- public class ExpenseService : IExpenseService
- {
- private readonly IExpenseRepository expenseRepository;
- private readonly IUnitOfWork unitOfWork;
- public ExpenseService(IExpenseRepository expenseRepository, IUnitOfWork unitOfWork)
- {
- this.expenseRepository = expenseRepository;
- this.unitOfWork = unitOfWork;
- }
- public IEnumerable GetExpenses(DateTime startDate, DateTime endDate)
- {
- var expenses = expenseRepository.GetMany(exp => exp.Date >= startDate && exp.Date <= endDate);
- return expenses;
- }
- public void CreateExpense(Expense expense)
- {
- expenseRepository.Add(expense);
- SaveExpense();
- }
- public Expense GetExpense(int id)
- {
- var expense = expenseRepository.GetById(id);
- return expense;
- }
- public void DeleteExpense(int id)
- {
- var expense = expenseRepository.GetById(id);
- expenseRepository.Delete(expense);
- SaveExpense();
- }
- public void SaveExpense()
- {
- unitOfWork.Commit();
- }
- }
-}
diff --git a/MyFinance.Service/SecurityService.cs b/MyFinance.Service/SecurityService.cs
deleted file mode 100644
index 7bff167..0000000
--- a/MyFinance.Service/SecurityService.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MyFinance.Domain;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Data;
-
-
-namespace MyFinance.Service
-{
- public interface ISecurityService
- {
- IEnumerable GetUsers();
- User GetUser(string userName);
- void CreateUser(User user);
- void DeleteUser(string userName);
-
- IEnumerable Roles();
- Role GetRole(string roleName);
- void CreateRole(Role role);
- void DeleteRole(string roleName);
- void Save();
-
- void AssignRole(string userName, List roleNames);
-
-
- }
- public class SecurityService : ISecurityService
- {
- private readonly IUserRepository userRepository;
- private readonly IRoleRepository roleRepository;
- private readonly IUnitOfWork unitOfWork;
- public SecurityService(IUserRepository userRepository,IRoleRepository roleRepository, IUnitOfWork unitOfWork)
- {
- this.userRepository = userRepository;
- this.roleRepository = roleRepository;
- this.unitOfWork = unitOfWork;
- }
- public IEnumerable GetUsers()
- {
- var users = userRepository.GetAll();
- return users;
- }
-
- public User GetUser(string userName)
- {
- var user = userRepository.GetById(userName);
- return user;
- }
-
- public void CreateUser(User user)
- {
- userRepository.Add(user);
- Save();
- }
-
- public void DeleteUser(string userName)
- {
- var user = GetUser(userName);
- userRepository.Delete(user);
- Save();
- }
-
- public IEnumerable Roles()
- {
- var roles = roleRepository.GetAll();
- return roles;
- }
-
- public Role GetRole(string roleName)
- {
- var role = roleRepository.GetById(roleName);
- return role;
- }
-
- public void CreateRole(Role role)
- {
- roleRepository.Add(role);
- Save();
- }
-
- public void DeleteRole(string roleName)
- {
- var role = GetRole(roleName);
- roleRepository.Delete(role);
- Save();
- }
- public void AssignRole(string userName, List roleNames)
- {
- userRepository.AssignRole(userName, roleNames);
- Save();
- }
-
- public void Save()
- {
- unitOfWork.Commit();
- }
-
- }
-}
diff --git a/MyFinance.Web/AppStart_51Degrees.cs b/MyFinance.Web/AppStart_51Degrees.cs
deleted file mode 100644
index e8771ab..0000000
--- a/MyFinance.Web/AppStart_51Degrees.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/* *********************************************************************
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the License for the specific language governing rights and
- * limitations under the License.
- *
- * The Original Code is named .NET Mobile API, first released under
- * this licence on 11th March 2009.
- *
- * The Initial Developer of the Original Code is owned by
- * 51 Degrees Mobile Experts Limited. Portions created by 51 Degrees
- * Mobile Experts Limited are Copyright (C) 2009 - 2010. All Rights Reserved.
- *
- * Contributor(s):
- * James Rosewell
- *
- * ********************************************************************* */
-
-using System;
-using System.Web.Configuration;
-
-[assembly: WebActivator.PreApplicationStartMethod(typeof(MyFinance.Web.AppStart_51Degrees), "Start")]
-
-namespace MyFinance.Web {
- public static class AppStart_51Degrees {
- public static void Start() {
- // Enable the mobile detection provider.
- HttpCapabilitiesBase.BrowserCapabilitiesProvider =
- new FiftyOne.Foundation.Mobile.Detection.MobileCapabilitiesProvider();
- }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/App_Code/TwitterGoodies.cshtml b/MyFinance.Web/App_Code/TwitterGoodies.cshtml
deleted file mode 100644
index f74886b..0000000
--- a/MyFinance.Web/App_Code/TwitterGoodies.cshtml
+++ /dev/null
@@ -1,332 +0,0 @@
-@functions {
- public enum DataCount {
- Vertical,
- Horizontal,
- None
- }
-
- public enum Languages {
- English,
- French,
- German,
- Spanish,
- Japanese
- }
-
- public static string GetLanguageCode(Languages language) {
- switch (language) {
- case Languages.French:
- return "fr";
- case Languages.German:
- return "de";
- case Languages.Spanish:
- return "es";
- case Languages.Japanese:
- return "ja";
- default:
- return "";
- }
- }
-
- public enum FollowStyles {
- Text,
- Bird,
- Twitter,
- LogoBig,
- LogoMedium,
- LogoSmall
- }
-
- public enum FollowColors {
- Blue,
- Silver,
- Black
- }
-
- public static string GetFollowButtonImageUrl(FollowStyles followStyle, FollowColors followColor) {
- var fileName = "";
-
- switch (followStyle) {
- case FollowStyles.Text:
- fileName = "follow_me-";
- break;
- case FollowStyles.Bird:
- fileName = "follow_bird-";
- break;
- case FollowStyles.Twitter:
- fileName = "twitter-";
- break;
- case FollowStyles.LogoBig:
- fileName = "t_logo-";
- break;
- case FollowStyles.LogoMedium:
- fileName = "t_small-";
- break;
- case FollowStyles.LogoSmall:
- fileName = "t_mini-";
- break;
- }
- switch (followColor) {
- case FollowColors.Blue:
- fileName += "a";
- break;
- case FollowColors.Silver:
- fileName += "b";
- break;
- case FollowColors.Black:
- fileName += "c";
- break;
- }
-
- return fileName;
- }
-
- public enum WidgetBehaviors {
- Default,
- All
- }
-}
-
-@helper TweetButton(
- DataCount dataCount = DataCount.Vertical,
- string tweetText = "",
- string url = "",
- Languages language = Languages.English,
- string username = "",
- string relatedUsername = "",
- string relatedUserDescription = "") {
- var tweetTextAttribute = new HtmlString(!tweetText.IsEmpty() ? string.Format(" data-text=\"{0}\"", tweetText) : "");
- var urlAttribute = new HtmlString(!url.IsEmpty() ? string.Format(" data-url=\"{0}\"", url) : "");
- var languageAttribute = new HtmlString(!GetLanguageCode(language).IsEmpty() ? string.Format(" data-lang=\"{0}\"", GetLanguageCode(language)) : "");
- var usernameAttribute = new HtmlString(!username.IsEmpty() ? string.Format(" data-via=\"{0}\"", username) : "");
- var relatedAttribute = new HtmlString(!relatedUsername.IsEmpty() ? string.Format(" data-related=\"{0}{1}\"", relatedUsername, !relatedUserDescription.IsEmpty() ? ":" + relatedUserDescription : "") : "");
-
-}
-
-@helper FollowButton(
- string username,
- FollowStyles followStyle = FollowStyles.Text,
- FollowColors followColor = FollowColors.Blue) {
-
-}
-
-@helper Profile(
- string username,
- int width = 250,
- int height = 300,
- string backgroundShellColor = "#333333",
- string shellColor = "#ffffff",
- string tweetsBackgroundColor = "#000000",
- string tweetsColor = "#ffffff",
- string tweetsLinksColor = "#4aed05",
- int numberOfTweets = 4,
- bool scrollBar = false,
- bool loop = false,
- bool live = false,
- bool hashTags = true,
- bool timestamp = true,
- bool avatars = false,
- WidgetBehaviors behavior = WidgetBehaviors.All,
- int interval = 6) {
-
-
-}
-
-@* Advanced queries: http://search.twitter.com/operators *@
-@helper Search(
- string searchQuery,
- int width = 250,
- int height = 300,
- string title = null,
- string caption = null,
- string backgroundShellColor = "#8ec1da",
- string shellColor = "#ffffff",
- string tweetsBackgroundColor = "#ffffff",
- string tweetsColor = "#444444",
- string tweetsLinksColor = "#1985b5",
- bool scrollBar = false,
- bool loop = true,
- bool live = true,
- bool hashTags = true,
- bool timestamp = true,
- bool avatars = true,
- bool topTweets = true,
- WidgetBehaviors behavior = WidgetBehaviors.All,
- int interval = 6) {
-
-
-}
-
-@helper Faves(
- string username,
- int width = 250,
- int height = 300,
- string title = null,
- string caption = null,
- string backgroundShellColor = "#43c43f",
- string shellColor = "#ffffff",
- string tweetsBackgroundColor = "#ffffff",
- string tweetsColor = "#444444",
- string tweetsLinksColor = "#43c43f",
- int numberOfTweets = 10,
- bool scrollBar = true,
- bool loop = false,
- bool live = true,
- bool hashTags = true,
- bool timestamp = true,
- bool avatars = true,
- bool topTweets = true,
- WidgetBehaviors behavior = WidgetBehaviors.All,
- int interval = 6) {
-
-
-}
-
-@helper List(
- string username,
- string list,
- int width = 250,
- int height = 300,
- string title = null,
- string caption = null,
- string backgroundShellColor = "#ff96e7",
- string shellColor = "#ffffff",
- string tweetsBackgroundColor = "#ffffff",
- string tweetsColor = "#444444",
- string tweetsLinksColor = "#b740c2",
- int numberOfTweets = 30,
- bool scrollBar = true,
- bool loop = false,
- bool live = true,
- bool hashTags = true,
- bool timestamp = true,
- bool avatars = true,
- bool topTweets = true,
- WidgetBehaviors behavior = WidgetBehaviors.All,
- int interval = 6) {
-
-
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Content/Mobile.css b/MyFinance.Web/Areas/Mobile/Content/Mobile.css
deleted file mode 100644
index 7a924bd..0000000
--- a/MyFinance.Web/Areas/Mobile/Content/Mobile.css
+++ /dev/null
@@ -1,74 +0,0 @@
-body
-{
- background-color: #fff;
- font-size: 0.9em;
-}
-
-.page
-{
- width: auto;
-}
-
-h2
-{
- font-size: 1.2em;
- margin-bottom: 5px;
-}
-
-p, ul
-{
- margin: 5px 0 10px 0;
-}
-
-#header
-{
- background-color: #5c87b2;
- padding: 10px;
-}
-
-#main
-{
- padding: 10px;
-}
-
-#header h1
-{
- line-height: normal;
- font-size: 1.6em !important;
- padding-top: 0;
-}
-
-div#title
-{
- float: none;
-}
-
-#logindisplay
-{
- text-align: left;
- margin:0;
-}
-
-#menucontainer
-{
- margin-top: 10px;
-}
-
-ul#menu
-{
- text-align: left;
- margin: 0;
- padding: 0;
-}
-
-ul#menu li a
-{
- padding: 5px 15px;
- line-height: normal;
-}
-
-span.field-validation-error
-{
- display: block;
- margin-top: 5px;
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Controllers/CategoryController.cs b/MyFinance.Web/Areas/Mobile/Controllers/CategoryController.cs
deleted file mode 100644
index fee5780..0000000
--- a/MyFinance.Web/Areas/Mobile/Controllers/CategoryController.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using MyFinance.Data;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Domain;
-using MyFinance.Helpers;
-using MyFinance.Service;
-using MyFinance.Web.Helpers;
-
-namespace MyFinance.Web.Areas.Mobile.Controllers
-{
- public class CategoryController : Controller
- {
- private readonly ICategoryService categoryService;
-
- public CategoryController(ICategoryService categoryService)
- {
- this.categoryService = categoryService;
-
- }
- public ActionResult Index()
- {
- var categories = categoryService.GetCategories();
- return View(categories);
- }
- [HttpGet]
- public ActionResult Edit(int id)
- {
-
- var category = categoryService.GetCategory(id);
- return View(category);
- }
-
- [HttpPost]
- public ActionResult Edit(int id, FormCollection collection)
- {
-
- var category = categoryService.GetCategory(id);
- if (TryUpdateModel(category))
- {
- categoryService.SaveCategory();
- return RedirectToAction("Index");
- }
- else return View(category);
- }
-
- [HttpGet]
- public ActionResult Create()
- {
- var category = new Category();
- return View(category);
- }
-
- [HttpPost]
- public ActionResult Create(Category category)
- {
- if (!ModelState.IsValid)
- {
- return View(category);
- }
- categoryService.CreateCategory(category);
- return RedirectToAction("Index");
- }
-
- public ActionResult Delete(int id)
- {
- categoryService.DeleteCategory(id);
- var categories = categoryService.GetCategories();
- return RedirectToAction("Index");
- }
-
- }
-}
diff --git a/MyFinance.Web/Areas/Mobile/MobileAreaRegistration.cs b/MyFinance.Web/Areas/Mobile/MobileAreaRegistration.cs
deleted file mode 100644
index c20701d..0000000
--- a/MyFinance.Web/Areas/Mobile/MobileAreaRegistration.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Web.Mvc;
-
-namespace MyFinance.Web.Areas.Mobile
-{
- public class MobileAreaRegistration : AreaRegistration
- {
- public override string AreaName
- {
- get
- {
- return "Mobile";
- }
- }
-
- public override void RegisterArea(AreaRegistrationContext context)
- {
- context.MapRoute(
- "Mobile_default",
- "Mobile/{controller}/{action}/{id}",
- new { controller = "Home", action = "Index", id = UrlParameter.Optional }
- );
- }
- }
-}
diff --git a/MyFinance.Web/Areas/Mobile/Views/Category/CategoryList.cshtml b/MyFinance.Web/Areas/Mobile/Views/Category/CategoryList.cshtml
deleted file mode 100644
index 3ce0ee2..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Category/CategoryList.cshtml
+++ /dev/null
@@ -1,28 +0,0 @@
-@using MyFinance.Helpers;
-@using MyFinance.Domain;
-@model IEnumerable
-
-
-
Category List
- @Html.ActionLink("Create New Category", "Create",null, new { @class = "ui-btn-right" })
-
-
-
- Categories
- @foreach (var item in Model)
- {
-
- @item.Name
- @item.Description
-
-
- Delete
-
- Edit
-
-
- }
-@* *@
-
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Views/Category/Create.cshtml b/MyFinance.Web/Areas/Mobile/Views/Category/Create.cshtml
deleted file mode 100644
index 403fa8a..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Category/Create.cshtml
+++ /dev/null
@@ -1,30 +0,0 @@
-@model MyFinance.Domain.Category
-@{
- ViewBag.Title = "Create Category";
-}
-
-
-
Create Category
- @Html.ActionLink("Home", "Index","Home",null, new { @class = "ui-btn-right" })
-
-
-
- @using (Html.BeginForm("Create","Category",FormMethod.Post))
- {
-
- @Html.LabelFor(model => model.Name)
- @Html.EditorFor(model => model.Name)
-
- @Html.ValidationMessageFor(m => m.Name)
-
-
-
- @Html.LabelFor(model => model.Description)
- @Html.EditorFor(model => model.Description)
-
-
- Save
-
- }
-
-
diff --git a/MyFinance.Web/Areas/Mobile/Views/Category/Edit.cshtml b/MyFinance.Web/Areas/Mobile/Views/Category/Edit.cshtml
deleted file mode 100644
index b49f56d..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Category/Edit.cshtml
+++ /dev/null
@@ -1,33 +0,0 @@
-@model MyFinance.Domain.Category
-@{
- ViewBag.Title = "Edit Category";
-}
-
-
-
Edit Category
- @Html.ActionLink("Home", "Index","Home",null, new { @class = "ui-btn-right" })
-
-
-
- @using (Html.BeginForm("Edit", "Category", FormMethod.Post))
- {
-
- @Html.HiddenFor(model => model.CategoryId)
-
-
- @Html.LabelFor(model => model.Name)
- @Html.EditorFor(model => model.Name)
-
-
- @Html.ValidationMessageFor(m => m.Name)
-
-
- @Html.LabelFor(model => model.Description)
- @Html.EditorFor(model => model.Description)
-
-
- Save
-
- }
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Views/Category/Index.cshtml b/MyFinance.Web/Areas/Mobile/Views/Category/Index.cshtml
deleted file mode 100644
index bc53247..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Category/Index.cshtml
+++ /dev/null
@@ -1,7 +0,0 @@
-@model IEnumerable
-@{
- ViewBag.Title = "Index";
-}
-
- @Html.Partial("CategoryList", Model)
-
diff --git a/MyFinance.Web/Areas/Mobile/Views/Home/Index.cshtml b/MyFinance.Web/Areas/Mobile/Views/Home/Index.cshtml
deleted file mode 100644
index 005dc4c..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Home/Index.cshtml
+++ /dev/null
@@ -1,22 +0,0 @@
-@{
- ViewBag.Title = "Index";
-}
-
-
-
Expense Tracker Mobile
-
-
-
- @Html.Partial("_LogOnPartial")
- @Html.ActionLink("Home", "Index", "Home")
- @Html.ActionLink("Category", "Index", "Category")
- @Html.ActionLink("Expense", "Index", "Expense")
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Views/Shared/_Layout.cshtml b/MyFinance.Web/Areas/Mobile/Views/Shared/_Layout.cshtml
deleted file mode 100644
index 8d82c44..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/Shared/_Layout.cshtml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
- @ViewBag.Title
-
-
-
-
-
-
- @RenderBody()
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/Areas/Mobile/Views/_ViewStart.cshtml b/MyFinance.Web/Areas/Mobile/Views/_ViewStart.cshtml
deleted file mode 100644
index 6c5c0d9..0000000
--- a/MyFinance.Web/Areas/Mobile/Views/_ViewStart.cshtml
+++ /dev/null
@@ -1,3 +0,0 @@
-@{
- Layout = "~/Areas/Mobile/Views/Shared/_Layout.cshtml";
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Content/Site-Rounds.css b/MyFinance.Web/Content/Site-Rounds.css
deleted file mode 100644
index 4865894..0000000
--- a/MyFinance.Web/Content/Site-Rounds.css
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-----------------------------------------------------------*/
-body {background:#5c87b2 url(bg-main.png) repeat-x;font-size:.75em;font-family:Verdana, Helvetica, Sans-Serif;margin:20px 0;padding:0;color:#696969;}
-a:link {color:#034af3;text-decoration:underline;}
-a:visited {color:#505abc;}
-a:hover {color:#1d60ff;text-decoration:none;}
-a:active {color:#12eb87;}
-p, ul {margin-bottom:20px;}
-
-/* HEADINGS
-----------------------------------------------------------*/
-h1, h2, h3, h4, h5, h6 {font-size:1.5em;color:#000;font-family:Arial, Helvetica, sans-serif;}
-h1 {font-size:2em;padding-bottom:0;margin-bottom:0;}
-h2 {padding:0 0 10px 0;}
-h3 {font-size:1.2em;}
-h4 {font-size:1.1em;}
-h5, h6 {font-size:1em;}
-/* this rule styles tags that are the
-first child of the left and right table columns */
-.rightColumn > h1, .rightColumn > h2, .leftColumn > h1, .leftColumn > h2 {margin-top:0;}
-
-/* PRIMARY LAYOUT ELEMENTS
-----------------------------------------------------------*/
-.page {width:950px;margin-left:auto;margin-right:auto;}
-#header {position:relative;margin:0;color:#000;padding:25px 0 0 0;width:950px;}
- #header h1 {padding:0;margin:0;color:#fff;border:none;font-family:Arial, Helvetica, sans-serif;font-size:1.7em;}
- #title {display:block;width:270px;float:right;margin:1px 0 0 15px;}
- #logindisplay {font-size:1.1em;display:block;text-align:right;color:#ccc;width:300px;position:absolute;top:-19px;right:15px;font-weight:bold; font-family:Arial, Helvetica, sans-serif;}
- #menucontainer {float:left;}
-#main {padding:30px 30px 15px 30px;background:#fff url(bg-main-corner-sprite.png) no-repeat;margin-bottom:30px;_height:1px;clear:both;position:relative;width:890px;}
-#footer {color:#999;padding:30px 0;text-align:center;position:absolute;bottom:-70px;left:0;font-size:.9em;background:#FFF url(bg-main-corner-sprite.png) no-repeat -950px bottom;width:950px;}
-/* TAB MENU
-----------------------------------------------------------*/
-ul#menu {padding:0;position:relative;margin:0 0 0 15px ;text-align:right;}
-ul#menu li {display:block;list-style:none;background:#e8eef4 url(bg-nav-corner-sprite.png) no-repeat 0 -150px;float:left;margin:0 2px 0 0;}
-ul#menu li a {padding:15px 20px;font-weight:bold;text-decoration:none;color:#034af3;background: transparent url(bg-nav-corner-sprite.png) no-repeat right -150px;display:block;}
-ul#menu li a:hover {text-decoration:none;color:#000;}
-ul#menu li a:active {text-decoration:none;color:#009933;}
-ul#menu li.selected {background:#fff url(bg-nav-corner-sprite.png) no-repeat 0 -150px;}
-ul#menu li.selected a {color:#000;}
-
-/* MISC
-----------------------------------------------------------*/
-.clear {clear:both;}
-.error {color:Red;}
-#logindisplay a:link, #logindisplay a:visited {color:#034af3;text-decoration:none;}
-#logindisplay a:hover {color:#034af3;text-decoration:underline;}
-.field-validation-error {color:#ff0000;}
-.input-validation-error {border:1px solid #ff0000;background-color:#ffeeee;}
-.validation-summary-errors {font-weight:bold;color:#ff0000;}
diff --git a/MyFinance.Web/Content/Site.css b/MyFinance.Web/Content/Site.css
deleted file mode 100644
index 6b0a06c..0000000
--- a/MyFinance.Web/Content/Site.css
+++ /dev/null
@@ -1,345 +0,0 @@
-/*----------------------------------------------------------
-The base color for this template is #5c87b2. If you'd like
-to use a different color start by replacing all instances of
-#5c87b2 with your new color.
-----------------------------------------------------------*/
-body
-{
- background-color: #5c87b2;
- font-size: 75%;
- font-family: Verdana, Tahoma, Arial, "Helvetica Neue", Helvetica, Sans-Serif;
- margin: 0;
- padding: 0;
- color: #696969;
-}
-
-a:link
-{
- color: #034af3;
- text-decoration: underline;
-}
-a:visited
-{
- color: #505abc;
-}
-a:hover
-{
- color: #1d60ff;
- text-decoration: none;
-}
-a:active
-{
- color: #12eb87;
-}
-
-p, ul
-{
- margin-bottom: 20px;
- line-height: 1.6em;
-}
-
-/* HEADINGS
-----------------------------------------------------------*/
-h1, h2, h3, h4, h5, h6
-{
- font-size: 1.5em;
- color: #000;
-}
-
-h1
-{
- font-size: 2em;
- padding-bottom: 0;
- margin-bottom: 0;
-}
-h2
-{
- padding: 0 0 10px 0;
-}
-h3
-{
- font-size: 1.2em;
-}
-h4
-{
- font-size: 1.1em;
-}
-h5, h6
-{
- font-size: 1em;
-}
-
-/* this rule styles tags that are the
-first child of the left and right table columns */
-.rightColumn > h1, .rightColumn > h2, .leftColumn > h1, .leftColumn > h2
-{
- margin-top: 0;
-}
-
-/* PRIMARY LAYOUT ELEMENTS
-----------------------------------------------------------*/
-
-/* you can specify a greater or lesser percentage for the
-page width. Or, you can specify an exact pixel width. */
-.page
-{
- width: 90%;
- margin-left: auto;
- margin-right: auto;
-}
-
-#header
-{
- position: relative;
- margin-bottom: 0px;
- color: #000;
- padding: 0;
-}
-
-#header h1
-{
- font-weight: bold;
- padding: 5px 0;
- margin: 0;
- color: #fff;
- border: none;
- line-height: 2em;
- font-size: 32px !important;
-}
-
-#main
-{
- padding: 30px 30px 15px 30px;
- background-color: #fff;
- margin-bottom: 30px;
- _height: 1px; /* only IE6 applies CSS properties starting with an underscore */
-}
-
-#footer
-{
- color: #999;
- padding: 10px 0;
- text-align: center;
- line-height: normal;
- margin: 0;
- font-size: .9em;
-}
-
-/* TAB MENU
-----------------------------------------------------------*/
-ul#menu
-{
- border-bottom: 1px #5C87B2 solid;
- padding: 0 0 2px;
- position: relative;
- margin: 0;
- text-align: right;
-}
-
-ul#menu li
-{
- display: inline;
- list-style: none;
-}
-
-ul#menu li#greeting
-{
- padding: 10px 20px;
- font-weight: bold;
- text-decoration: none;
- line-height: 2.8em;
- color: #fff;
-}
-
-ul#menu li a
-{
- padding: 10px 20px;
- font-weight: bold;
- text-decoration: none;
- line-height: 2.8em;
- background-color: #e8eef4;
- color: #034af3;
-}
-
-ul#menu li a:hover
-{
- background-color: #fff;
- text-decoration: none;
-}
-
-ul#menu li a:active
-{
- background-color: #a6e2a6;
- text-decoration: none;
-}
-
-ul#menu li.selected a
-{
- background-color: #fff;
- color: #000;
-}
-
-/* FORM LAYOUT ELEMENTS
-----------------------------------------------------------*/
-
-fieldset
-{
- border:1px solid #ddd;
- padding:0 1.4em 1.4em 1.4em;
- margin:0 0 1.5em 0;
-}
-
-legend
-{
- font-size:1.2em;
- font-weight: bold;
-}
-
-textarea
-{
- min-height: 75px;
-}
-
-input[type="text"]
-{
- width: 200px;
- border: 1px solid #CCC;
-}
-
-input[type="password"]
-{
- width: 200px;
- border: 1px solid #CCC;
-}
-
-/* TABLE
-----------------------------------------------------------*/
-
-table
-{
- border: solid 1px #e8eef4;
- border-collapse: collapse;
-}
-
-table td
-{
- padding: 5px;
- border: solid 1px #e8eef4;
-}
-
-table th
-{
- padding: 6px 5px;
- text-align: left;
- background-color: #e8eef4;
- border: solid 1px #e8eef4;
-}
-
-/* MISC
-----------------------------------------------------------*/
-.clear
-{
- clear: both;
-}
-
-.error
-{
- color:Red;
-}
-
-#menucontainer
-{
- margin-top:40px;
-}
-
-div#title
-{
- display:block;
- float:left;
- text-align:left;
-}
-
-#logindisplay
-{
- font-size:1.1em;
- display:block;
- text-align:right;
- margin:10px;
- color:White;
-}
-
-#logindisplay a:link
-{
- color: white;
- text-decoration: underline;
-}
-
-#logindisplay a:visited
-{
- color: white;
- text-decoration: underline;
-}
-
-#logindisplay a:hover
-{
- color: white;
- text-decoration: none;
-}
-
-/* Styles for validation helpers
------------------------------------------------------------*/
-.field-validation-error
-{
- color: #ff0000;
-}
-
-.field-validation-valid
-{
- display: none;
-}
-
-.input-validation-error
-{
- border: 1px solid #ff0000;
- background-color: #ffeeee;
-}
-
-.validation-summary-errors
-{
- font-weight: bold;
- color: #ff0000;
-}
-
-.validation-summary-valid
-{
- display: none;
-}
-
-/* Styles for editor and display helpers
-----------------------------------------------------------*/
-.display-label,
-.editor-label
-{
- margin: 1em 0 0 0;
-}
-
-.display-field,
-.editor-field
-{
- margin:0.5em 0 0 0;
-}
-
-.text-box
-{
- width: 30em;
-}
-
-.text-box.multi-line
-{
- height: 6.5em;
-}
-
-.tri-state
-{
- width: 6em;
-}
diff --git a/MyFinance.Web/Content/Site_alt.css b/MyFinance.Web/Content/Site_alt.css
deleted file mode 100644
index 0ec4658..0000000
--- a/MyFinance.Web/Content/Site_alt.css
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-----------------------------------------------------------*/
-body { font-size: .7em; font-family: Verdana, Helvetica, Sans-Serif; margin: 0 0 20px 0; padding: 0; color: #474747; background:#5c87b2;}
-a:link { color: #034af3; text-decoration: underline; }
-a:visited { color: #505abc; }
-a:hover { color: #1d60ff; text-decoration: none; }
-a:active { color: #12eb87; }
-p, ul { margin-bottom: 20px; line-height: 1.6em; }
-a {outline:none}
-img {border:none;}
-
-/* HEADINGS
-----------------------------------------------------------*/
-h1, h2, h3, h4, h5, h6 { font-size: 1.5em; color: #000; font-family: Arial, Helvetica, sans-serif; }
-h1 { font-size: 2em; padding-bottom: 0; margin-bottom: 0; }
-h2 { padding: 0 0 10px 0; }
-h3 { font-size: 1.2em; }
-h4 { font-size: 1.1em; }
-h5, h6 { font-size: 1em; }
-/* this rule styles tags that are the
-first child of the left and right table columns */
-.rightColumn > h1, .rightColumn > h2, .leftColumn > h1, .leftColumn > h2 { margin-top: 0; }
-
-/* PRIMARY LAYOUT ELEMENTS
-----------------------------------------------------------*/
-.page {width:950px;margin-left:auto;margin-right:auto;}
-#header {position:relative;margin:0;color:#000;padding:5px 0 0 0;width:950px;background:#5c87b2 url(bg-header.png) no-repeat center top;}
-#header h1 {padding:0 0 0 25px;margin:0;color:#000;border:none;font-family:Arial, Helvetica, sans-serif;font-size:1.6em;}
-#title {width:370px;padding:4px 0 35px 0;}
-#logindisplay {font-size:1.1em;display:block;text-align:right;color:#ccc;width:300px;position:absolute;top:13px;right:25px;font-weight:bold; font-family:Arial, Helvetica, sans-serif;}
-#menucontainer {}
-#main {padding:30px 30px 15px 30px;background:#fff url(bg-main-corner-sprite.png) no-repeat;margin-bottom:30px;_height:1px;clear:both;position:relative;width:890px;}
-#footer {clear:both;color:#999;padding:30px 0 0 0;text-align:center;}
-#bottom-shadow {position:absolute;bottom:0;left:0;font-size:.9em;background:#FFF url(bg-main-corner-sprite.png) no-repeat -950px bottom;width:950px;clear:both;height:15px;}
-
-/* TAB MENU
-----------------------------------------------------------*/
-ul#menu {padding:0;position:relative;margin:0 0 0 15px ;text-align:right;}
-ul#menu li {display:block;list-style:none;background:#e8eef4 url(bg-nav-corner-sprite.png) no-repeat 0 -150px;float:left;margin:0 2px 0 0;}
-ul#menu li a {padding:15px 12px;font-weight:bold;text-decoration:none;color:#034af3;background: transparent url(bg-nav-corner-sprite.png) no-repeat right -150px;display:block;}
-ul#menu li a:hover {text-decoration:none;color:#000;}
-ul#menu li a:active {text-decoration:none;color:#009933;}
-ul#menu li.selected {background:#fff url(bg-nav-corner-sprite.png) no-repeat 0 -150px;}
-ul#menu li.selected a {color:#000;}
-
-/* MISC
-----------------------------------------------------------*/
-.clear { clear: both; }
-.error { color:Red; }
-.field-validation-error { color: #ff0000; }
-.input-validation-error { border: 1px solid #ff0000; background-color: #ffeeee; }
-.validation-summary-errors { font-weight: bold; color: #ff0000; }
-.fields p { white-space:nowrap;margin-bottom:5px; }
-.first {padding-top:0;margin-top:0;}
-
-/* Contact Manager
-----------------------------------------------------------*/
-ul#leftColumn { float: left;margin:0;padding:20px 0 0 0; width:18%;font-weight:bold;}
-ul#leftColumn li { list-style:none;background:url(bg-nav-side-sprite.png) no-repeat -342px 0;padding:4px 0 0 0;}
-ul#leftColumn li a:link, #leftColumn li a:visited {display:block;padding:3px 8px 11px 10px; text-decoration:none;background:url(bg-nav-side-sprite.png) no-repeat -342px bottom; }
-ul#leftColumn li a:hover {color:#000;text-decoration:none;}
-ul#leftColumn li a:active, ul#leftColumn li.current-item a:active { background-color:#e8eef4; text-decoration:none;color:#000;}
-/* selected */
-ul#leftColumn li.selected {background-position:0 0;}
-ul#leftColumn li.selected a:link, #leftColumn li.selected a:visited {background-position: 0 bottom;color:#000;}
-.crumb {padding-top:0;margin-top:0;}
-/* listings container */
-#divContactList { float: left; padding:2%; background: #f1f7ed url(bg-inner-corners.png) no-repeat;min-height:300px;_height:300px; width:78%; position:relative; }
-.divContactList-bottom { background: #e8eef4 url(bg-inner-corners.png) no-repeat bottom right; position:absolute;bottom:0;left:0;height:6px;width:730px; }
-/* data table */
-table.data-table {width:100%;border:5px solid #f9fbfc;border-top:none; font-size:.9em;}
-table.data-table td, table.data-table th {padding:6px 10px; border-top:2px solid #eff3f7;background:#e7f0f3;}
-table.data-table th { text-align:left;}
-table.data-table thead th { background:#d7e6ec;border-top:5px solid #f9fbfc;color:#000;}
-table.data-table tbody th { background:#f1f6f8; border-top-color:#f9fbfc;}
-/* action cells */
-table.data-table td.actions, table.data-table th.actions {padding:0px;width:40px;}
-table.data-table td.actions {font-family:Arial, Helvetica, sans-serif;white-space:nowrap; text-align:center;border-right:1px dashed #d7e6ec;}
-table.data-table th.actions {font-weight:normal;color:#4d8aa2;text-align:center;}
-
-/* FORMS
-----------------------------------------------------------*/
-fieldset {padding:0 20px 20px 20px;border:1px solid #e3e3e3;}
-legend {font-size:1.6em;padding:0 10px 20px 10px;color:#000;}
-label {display:block;float:left;width:120px; text-align:right;margin:0 10px 0 0;}
-p.submit, p.checkbox {padding-left:130px;}
-p.checkbox label {display:inline;float:none;}
\ No newline at end of file
diff --git a/MyFinance.Web/Content/bg-header.png b/MyFinance.Web/Content/bg-header.png
deleted file mode 100644
index 047d71a..0000000
Binary files a/MyFinance.Web/Content/bg-header.png and /dev/null differ
diff --git a/MyFinance.Web/Content/bg-inner-corners.png b/MyFinance.Web/Content/bg-inner-corners.png
deleted file mode 100644
index f07b5cf..0000000
Binary files a/MyFinance.Web/Content/bg-inner-corners.png and /dev/null differ
diff --git a/MyFinance.Web/Content/bg-main.png b/MyFinance.Web/Content/bg-main.png
deleted file mode 100644
index 9065eda..0000000
Binary files a/MyFinance.Web/Content/bg-main.png and /dev/null differ
diff --git a/MyFinance.Web/Content/bg-nav-corner-sprite.png b/MyFinance.Web/Content/bg-nav-corner-sprite.png
deleted file mode 100644
index 49a6753..0000000
Binary files a/MyFinance.Web/Content/bg-nav-corner-sprite.png and /dev/null differ
diff --git a/MyFinance.Web/Content/bg-nav-side-sprite.png b/MyFinance.Web/Content/bg-nav-side-sprite.png
deleted file mode 100644
index 77a14b3..0000000
Binary files a/MyFinance.Web/Content/bg-nav-side-sprite.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/Thumbs.db b/MyFinance.Web/Content/images/Thumbs.db
deleted file mode 100644
index e60fcbf..0000000
Binary files a/MyFinance.Web/Content/images/Thumbs.db and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-anim_basic_16x16.gif b/MyFinance.Web/Content/images/ui-anim_basic_16x16.gif
deleted file mode 100644
index 085ccae..0000000
Binary files a/MyFinance.Web/Content/images/ui-anim_basic_16x16.gif and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/MyFinance.Web/Content/images/ui-bg_diagonals-thick_18_b81900_40x40.png
deleted file mode 100644
index 954e22d..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diagonals-thick_18_b81900_40x40.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diagonals-thick_20_666666_40x40.png b/MyFinance.Web/Content/images/ui-bg_diagonals-thick_20_666666_40x40.png
deleted file mode 100644
index 64ece57..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diagonals-thick_20_666666_40x40.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_10_4f4221_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_10_4f4221_10x8.png
deleted file mode 100644
index fc3262e..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_10_4f4221_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_20_372806_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_20_372806_10x8.png
deleted file mode 100644
index aba2c18..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_20_372806_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_25_675423_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_25_675423_10x8.png
deleted file mode 100644
index 753b82c..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_25_675423_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_25_d5ac5d_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_25_d5ac5d_10x8.png
deleted file mode 100644
index 5873472..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_25_d5ac5d_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_8_261803_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_8_261803_10x8.png
deleted file mode 100644
index 27d918c..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_8_261803_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_diamond_8_443113_10x8.png b/MyFinance.Web/Content/images/ui-bg_diamond_8_443113_10x8.png
deleted file mode 100644
index 722ae7f..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_diamond_8_443113_10x8.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_flat_10_000000_40x100.png b/MyFinance.Web/Content/images/ui-bg_flat_10_000000_40x100.png
deleted file mode 100644
index e69de29..0000000
diff --git a/MyFinance.Web/Content/images/ui-bg_flat_75_ddd4b0_40x100.png b/MyFinance.Web/Content/images/ui-bg_flat_75_ddd4b0_40x100.png
deleted file mode 100644
index f5cc553..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_flat_75_ddd4b0_40x100.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_100_f6f6f6_1x400.png b/MyFinance.Web/Content/images/ui-bg_glass_100_f6f6f6_1x400.png
deleted file mode 100644
index 9b383f4..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_glass_100_f6f6f6_1x400.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_glass_100_fdf5ce_1x400.png b/MyFinance.Web/Content/images/ui-bg_glass_100_fdf5ce_1x400.png
deleted file mode 100644
index 859c264..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_glass_100_fdf5ce_1x400.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/MyFinance.Web/Content/images/ui-bg_gloss-wave_35_f6a828_500x100.png
deleted file mode 100644
index 39d5824..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_gloss-wave_35_f6a828_500x100.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_highlight-hard_65_fee4bd_1x100.png b/MyFinance.Web/Content/images/ui-bg_highlight-hard_65_fee4bd_1x100.png
deleted file mode 100644
index 52d3a34..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_highlight-hard_65_fee4bd_1x100.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/MyFinance.Web/Content/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
deleted file mode 100644
index f127367..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_highlight-soft_100_eeeeee_1x100.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/MyFinance.Web/Content/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
deleted file mode 100644
index 359397a..0000000
Binary files a/MyFinance.Web/Content/images/ui-bg_highlight-soft_75_ffe45c_1x100.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_e8e2b5_256x240.png b/MyFinance.Web/Content/images/ui-icons_e8e2b5_256x240.png
deleted file mode 100644
index e349b59..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_e8e2b5_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_efec9f_256x240.png b/MyFinance.Web/Content/images/ui-icons_efec9f_256x240.png
deleted file mode 100644
index 232e4b9..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_efec9f_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_f2ec64_256x240.png b/MyFinance.Web/Content/images/ui-icons_f2ec64_256x240.png
deleted file mode 100644
index 734740c..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_f2ec64_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_f9f2bd_256x240.png b/MyFinance.Web/Content/images/ui-icons_f9f2bd_256x240.png
deleted file mode 100644
index 4ff4fd9..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_f9f2bd_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_ff7519_256x240.png b/MyFinance.Web/Content/images/ui-icons_ff7519_256x240.png
deleted file mode 100644
index 5445171..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_ff7519_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Content/images/ui-icons_ffd27a_256x240.png b/MyFinance.Web/Content/images/ui-icons_ffd27a_256x240.png
deleted file mode 100644
index baebb63..0000000
Binary files a/MyFinance.Web/Content/images/ui-icons_ffd27a_256x240.png and /dev/null differ
diff --git a/MyFinance.Web/Controllers/AccountController.cs b/MyFinance.Web/Controllers/AccountController.cs
deleted file mode 100644
index 52b90e1..0000000
--- a/MyFinance.Web/Controllers/AccountController.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Security.Principal;
-using System.Web;
-using System.Web.Mvc;
-using System.Web.Routing;
-using System.Web.Security;
-using MyFinance.Web.Models;
-
-namespace MyFinance.Web.Controllers
-{
- public class AccountController : Controller
- {
-
- public IFormsAuthenticationService FormsService { get; set; }
- public IMembershipService MembershipService { get; set; }
-
- protected override void Initialize(RequestContext requestContext)
- {
- if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
- if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
-
- base.Initialize(requestContext);
- }
-
- // **************************************
- // URL: /Account/LogOn
- // **************************************
-
- public ActionResult LogOn()
- {
- return View();
- }
-
- [HttpPost]
- public ActionResult LogOn(LogOnModel model, string returnUrl)
- {
- if (ModelState.IsValid)
- {
- if (MembershipService.ValidateUser(model.UserName, model.Password))
- {
- FormsService.SignIn(model.UserName, model.RememberMe);
- if (Url.IsLocalUrl(returnUrl))
- {
- return Redirect(returnUrl);
- }
- else
- {
- return RedirectToAction("Index", "Home");
- }
- }
- else
- {
- ModelState.AddModelError("", "The user name or password provided is incorrect.");
- }
- }
-
- // If we got this far, something failed, redisplay form
- return View(model);
- }
-
- // **************************************
- // URL: /Account/LogOff
- // **************************************
-
- public ActionResult LogOff()
- {
- FormsService.SignOut();
-
- return RedirectToAction("Index", "Home");
- }
-
- // **************************************
- // URL: /Account/Register
- // **************************************
-
- public ActionResult Register()
- {
- ViewBag.PasswordLength = MembershipService.MinPasswordLength;
- return View();
- }
-
- [HttpPost]
- public ActionResult Register(RegisterModel model)
- {
- if (ModelState.IsValid)
- {
- // Attempt to register the user
- MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
-
- if (createStatus == MembershipCreateStatus.Success)
- {
- FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
- return RedirectToAction("Index", "Home");
- }
- else
- {
- ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
- }
- }
-
- // If we got this far, something failed, redisplay form
- ViewBag.PasswordLength = MembershipService.MinPasswordLength;
- return View(model);
- }
-
- // **************************************
- // URL: /Account/ChangePassword
- // **************************************
-
- [Authorize]
- public ActionResult ChangePassword()
- {
- ViewBag.PasswordLength = MembershipService.MinPasswordLength;
- return View();
- }
-
- [Authorize]
- [HttpPost]
- public ActionResult ChangePassword(ChangePasswordModel model)
- {
- if (ModelState.IsValid)
- {
- if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
- {
- return RedirectToAction("ChangePasswordSuccess");
- }
- else
- {
- ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
- }
- }
-
- // If we got this far, something failed, redisplay form
- ViewBag.PasswordLength = MembershipService.MinPasswordLength;
- return View(model);
- }
-
- // **************************************
- // URL: /Account/ChangePasswordSuccess
- // **************************************
-
- public ActionResult ChangePasswordSuccess()
- {
- return View();
- }
-
- }
-}
diff --git a/MyFinance.Web/Controllers/CategoryController.cs b/MyFinance.Web/Controllers/CategoryController.cs
deleted file mode 100644
index 56ce4cb..0000000
--- a/MyFinance.Web/Controllers/CategoryController.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using MyFinance.Data;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Domain;
-using MyFinance.Helpers;
-using MyFinance.Service;
-using MyFinance.Web.Helpers;
-namespace MyFinance.Web.Controllers
-{
-
-public class CategoryController : Controller
-{
- private readonly ICategoryService categoryService;
-
- public CategoryController(ICategoryService categoryService)
- {
- this.categoryService = categoryService;
-
- }
- public ActionResult Index()
- {
- var categories = categoryService.GetCategories();
- return View(categories);
- }
- [HttpGet]
- public ActionResult Edit(int id)
- {
-
- var category = categoryService.GetCategory(id);
- return View(category);
- }
-
- [HttpPost]
- public ActionResult Edit(int id, FormCollection collection)
- {
-
- var category = categoryService.GetCategory(id);
- if (TryUpdateModel(category))
- {
- categoryService.SaveCategory();
- return RedirectToAction("Index");
- }
- else return View(category);
- }
-
- [HttpGet]
- public ActionResult Create()
- {
- var category = new Category();
- return View(category);
- }
-
- [HttpPost]
- public ActionResult Create(Category category)
- {
- if (!ModelState.IsValid)
- {
- return View(category);
- }
- categoryService.CreateCategory(category);
- return RedirectToAction("Index");
- }
-
- [HttpPost]
- public ActionResult Delete(int id)
- {
- categoryService.DeleteCategory(id);
- var categories = categoryService.GetCategories();
- return PartialView("CategoryList", categories);
-
- }
-}
-}
diff --git a/MyFinance.Web/Controllers/ExpenseController.cs b/MyFinance.Web/Controllers/ExpenseController.cs
deleted file mode 100644
index a97e786..0000000
--- a/MyFinance.Web/Controllers/ExpenseController.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using MyFinance.Data;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Domain;
-using MyFinance.Web.ViewModel;
-using MyFinance.Helpers;
-using MyFinance.Service;
-using Microsoft.Web.Mvc;
-namespace MyFinance.Web.Controllers
-{
- public class ExpenseController : Controller
- {
- private readonly IExpenseService expenseService;
- private readonly ICategoryService categoryService;
- public ExpenseController(IExpenseService expenseService, ICategoryService categoryService)
- {
- this.expenseService = expenseService;
- this.categoryService = categoryService;
- }
- public ActionResult Index(DateTime? startDate, DateTime? endDate)
- {
- //If date is not passed, take current month's first and last dte
- DateTime dtNow;
- dtNow = DateTime.Today;
- if (!startDate.HasValue)
- {
- startDate = new DateTime(dtNow.Year, dtNow.Month, 1);
- endDate = startDate.Value.AddMonths(1).AddDays(-1);
- }
- //take last date of start date's month, if end date is not passed
- if (startDate.HasValue && !endDate.HasValue)
- {
- endDate = (new DateTime(startDate.Value.Year, startDate.Value.Month, 1)).AddMonths(1).AddDays(-1);
- }
- var expenses = expenseService.GetExpenses(startDate.Value ,endDate.Value);
- //if request is Ajax will return partial view
- if (Request.IsAjaxRequest())
- {
- return PartialView("ExpenseList", expenses);
- }
- //set start date and end date to ViewBag dictionary
- ViewBag.StartDate = startDate.Value.ToShortDateString();
- ViewBag.EndDate = endDate.Value.ToShortDateString();
- //if request is not ajax
- return View(expenses);
- }
- public ActionResult Create()
- {
- var expenseModel = new ExpenseViewModel();
- var categories = categoryService.GetCategories();
- expenseModel.Category = categories.ToSelectListItems(-1);
- expenseModel.Date = DateTime.Today;
- return View(expenseModel);
- }
- [HttpPost]
- public ActionResult Create(ExpenseViewModel expenseViewModel)
- {
-
- if (!ModelState.IsValid)
- {
- var categories = categoryService.GetCategories();
- expenseViewModel.Category = categories.ToSelectListItems(expenseViewModel.CategoryId);
- return View("Save", expenseViewModel);
- }
- Expense expense=new Expense();
- ModelCopier.CopyModel(expenseViewModel,expense);
- expenseService.CreateExpense(expense);
- return RedirectToAction("Index");
-
- }
- // GET: /Expense/Edit
- public ActionResult Edit(int id)
- {
- var expenseModel = new ExpenseViewModel();
- var expense = expenseService.GetExpense(id);
- ModelCopier.CopyModel(expense, expenseModel);
- var categories = categoryService.GetCategories();
- expenseModel.Category = categories.ToSelectListItems(expense.Category.CategoryId);
- return View(expenseModel);
- }
- [HttpPost]
- public ActionResult Edit(ExpenseViewModel expenseViewModel)
- {
-
- if (!ModelState.IsValid)
- {
- var categories = categoryService.GetCategories();
- expenseViewModel.Category = categories.ToSelectListItems(expenseViewModel.CategoryId);
- return View("Save", expenseViewModel);
- }
- var expenseToEdit = expenseService.GetExpense(expenseViewModel.ExpenseId);
- ModelCopier.CopyModel(expenseViewModel, expenseToEdit);
- expenseService.SaveExpense();
- return RedirectToAction("Index");
- }
- public ActionResult Delete(int id)
- {
- expenseService.DeleteExpense(id);
- DateTime startDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
- DateTime endDate = startDate.AddMonths(1).AddDays(-1);
- var expenses = expenseService.GetExpenses(startDate, endDate);
- return PartialView("ExpenseList", expenses);
- }
- }
-}
diff --git a/MyFinance.Web/Facebook/Docs/content/Site.css b/MyFinance.Web/Facebook/Docs/content/Site.css
deleted file mode 100644
index e687314..0000000
--- a/MyFinance.Web/Facebook/Docs/content/Site.css
+++ /dev/null
@@ -1,125 +0,0 @@
-html { background: transparent url('images/webx-bkg.png') repeat-x; margin: 0; padding: 0; }
-body { font-family: "Segoe UI", Tahoma, Helvetica, Arial, Sans-Serif; margin: 0; padding: 0; line-height: 150%; background: transparent url('images/webx-content-bkg.jpg') no-repeat center top; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; color: #434343; }
-
-.container { width: 800px; margin: 0 auto 0 auto; padding: 40px 0 0 0; }
-.header { overflow:auto; }
-.header img { float: left; padding: 18px 25px 10px 0px; }
-.header p { font-weight: bold; }
-
-.setupImg { margin-top: 10px; margin-bottom: 5px; }
-
-h1 { font-size: 1.6em; font-weight: normal; margin-top: 30px; }
-h3 { font-size: 1.1em; font-weight: bold; }
-
-a { color: #577fae; }
-a:hover { color: #92a5bc; }
-
-.content { overflow: auto; font-size: 0.9em; padding: 10px 0 10px 0; }
-.content .start { float: left; padding: 0 20px 0 15px; }
-.content .resources { float: left; width: 369px; padding: 0 0 0 30px; border-left: 1px dotted #c7ccd3; }
-.twitter { border-top: 1px dotted #c7ccd3; width: 800px; margin: 0 auto 0 auto; padding: 20px 0 0 0; }
-.twitter .twitterfeed { margin: 0 auto 0 auto; width: 740px; }
-
-.azureInfo { width: 200px; }
-
-.footer { font-size: 0.7em; margin: 20px 0 20px 0; padding: 15px 0px 0px 0px; list-style: none; border-top: 1px dotted #c7ccd3; overflow: auto; }
-.footer li { width: 49%; text-align: left; float: left; color: #999999; }
-.footer li:first-child { width: 49%; text-align: right; float: right; color: #434343; }
-
-.code { background-color: White; border: Black 1px dotted; padding-left: 3px; line-height: 130%; margin-top: 5px; margin-bottom: 5px; padding:5px }
-
-.codeIndent1{ margin-left: 30px; }
-.codeIndent2{ margin-left: 60px; }
-
-.highlight { background-color:#e1e1e1; }
-
- table.plugins {
- width: 350px;
- border-collapse: collapse;
- text-align: center;
- margin: 20px;
-}
-
-.plugins th {
- font-weight: bold;
- border-bottom: 2px solid black;
-}
-
-.plugins td {
- border-bottom: 1px solid #CCCCCC;
-}
-
-.dg_table {
- border-collapse: collapse;
- font-family: "Trebuchet MS", Arial, Helvetica, Sans-Serif;
- font-weight: normal;
- text-align: left;
-}
-
-.dg_header {
- background-color: Grey;
- font-weight: bold;
- color: #FFF;
-}
-
-.dg_table th, .dg_table td {
- border:1px solid #C0C0C0;
- padding: 5px;
-}
-
-.dg_altrow {
- background-color: #EAF2D3;
- color: #000;
-}
-
-.dg_header a:active, .dg_header a:hover, .dg_header a:link, .dg_header a:visited {
- color: #FFF;
- text-decoration: none;
-}
-
-/*API Reference*/
-table.memberdecls {
- border-spacing: 0px;
- padding: 0px;
-}
-
-.mdescLeft, .mdescRight,
-.memItemLeft, .memItemRight,
-.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
- border: none;
- margin: 4px;
- padding: 1px 0 0 8px;
-}
-
-.mdescLeft, .mdescRight {
- padding: 0px 8px 4px 8px;
- color: #555;
-}
-
-.memItemLeft, .memItemRight, .memTemplParams {
- border-top: 1px solid #C4CFE5;
-}
-
-.memItemLeft, .memTemplItemLeft {
- white-space: nowrap;
- vertical-align: top;
-}
-
-.memItemLeft {
- text-align: right;
-}
-
-.memItemLeft, .memTemplItemLeft {
- white-space: nowrap;
-}
-
-.memTemplParams {
- color: #4665A2;
- white-space: nowrap;
-}
-
-.navLinks {
- float: right;
- margin-top: 20px;
- font-size: 12px;
-}
diff --git a/MyFinance.Web/Facebook/Docs/content/images/FBCoreSettings.png b/MyFinance.Web/Facebook/Docs/content/images/FBCoreSettings.png
deleted file mode 100644
index a611888..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/FBCoreSettings.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/FBCreateApplication.png b/MyFinance.Web/Facebook/Docs/content/images/FBCreateApplication.png
deleted file mode 100644
index e367a89..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/FBCreateApplication.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/webx-bkg.png b/MyFinance.Web/Facebook/Docs/content/images/webx-bkg.png
deleted file mode 100644
index ba6c809..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/webx-bkg.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/webx-content-bkg.jpg b/MyFinance.Web/Facebook/Docs/content/images/webx-content-bkg.jpg
deleted file mode 100644
index b125efe..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/webx-content-bkg.jpg and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/webx-icon.png b/MyFinance.Web/Facebook/Docs/content/images/webx-icon.png
deleted file mode 100644
index 0c67c28..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/webx-icon.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/wm-mysite-settings.png b/MyFinance.Web/Facebook/Docs/content/images/wm-mysite-settings.png
deleted file mode 100644
index 0ad2e3a..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/wm-mysite-settings.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/content/images/wm-site-settings.png b/MyFinance.Web/Facebook/Docs/content/images/wm-site-settings.png
deleted file mode 100644
index 711641f..0000000
Binary files a/MyFinance.Web/Facebook/Docs/content/images/wm-site-settings.png and /dev/null differ
diff --git a/MyFinance.Web/Facebook/Docs/reference.htm b/MyFinance.Web/Facebook/Docs/reference.htm
deleted file mode 100644
index 6307556..0000000
--- a/MyFinance.Web/Facebook/Docs/reference.htm
+++ /dev/null
@@ -1,375 +0,0 @@
-
-
-
- Facebook Helper for WebMatrix - Helper Reference
-
-
-
-
-
-
-
-
-
Helper Properties
-
- static string AppId
- Gets or sets the Facebook application id.
- static string AppSecret
- Gets or sets the Facebook application secret.
- static string MembershipDBName
- Gets or sets the name of the database used for storing the membership data.
- static string Language
- Gets or sets the code of the language used to display the Facebook plugins.
-
-
Helper Methods
-
-
-
- Method
- Requires Initialization
- Requires Publishing
-
-
- static void
- Initialize (string appId, string appSecret, [string membershipDBName])
- -
- -
-
-
-
- Initialize the helper with your Facebook application
- settings.
- If the 'membershipDBName' parameter is specified, Facebook membership integration
- will be enabled, allowing users to register and associate their Facebook
- user account (identified with the e-mail) with your site membership and the
- WebSecurity helper. In this case, the helper will initialize the WebSecurity
- WebMatrix helper automatically (if not done previously) and the store the
- membership information in the 'membershipDbName' database.
-
-
-
-
- @helper
- GetInitializationScripts()
- -
- -
-
-
-
- Initialize the Facebook JavaScript SDK to be able to support
- the XFBML tags of the social plugins.
-
-
-
-
- UserProfile
- GetFacebookUserProfile()
- Yes ( only Initialize(...) )
- No
-
-
-
- Retrieves the Facebook profile of current logged in user. See
- the section at the bottom of the page for details on the information you can
- access.
-
-
-
-
- static void
- AssociateMembershipAccount (string
- userName)
- Yes (only Initialize(...) )
- No
-
-
-
- Associates the specified user name (e.g. email, depending on
- your membership model) with the current Facebook User Id from the logged user.
- See the Facebook.Bakery sample Web site for an example on how to use this method.
-
-
-
-
- @helper
- LoginButton (string registerUrl,
- [string returnUrl], [string callbackUrl]
- [string buttonText],
- [bool autoLogoutLink],
- [string size],
- [string length],
- [bool showFaces], [string extendedPermissions])
- Yes
- No
-
-
-
- Shows a Facebok Login Button, with site membership
- integration, allowing users to login on your site with their Facebook account
- (e-mail).
- To use this method, you need to provide the 'membershipDbName' in the helper's
- Initialize method.
-
-
-
-
- @helper
- GetLoginButtonTagOnly ([string buttonText],
- [bool autoLogoutLink],
- [string size],
- [string length],
- [string onLogin],
- [bool showFaces],
- [string extendedPermissions])
- No
- No
-
-
-
- Shows a Facebook Login Button, without integrating Facebook login with your site membership.
-
-
-
-
- @helper
- LikeButton ([string href],
- [string buttonLayout],
- [bool showFaces],
- [int width],
- [int height],
- [string action],
- [string font], [string colorScheme], [string refLabel])
- No
- No
-
-
-
- Shows a Facebook Like Button. When the user clicks the Like button on your site, a story appears in the user's friends' News Feed with a link back to your website.
-
-
-
-
- @helper
- Comments ([string xid],
- [int width],
- [int numPosts],
- [bool reverseOrder],
- [bool removeRoundedBox])
- Yes
- No
-
-
-
- Shows a Facebook Comments plugin. The Comments Box easily enables your users to comment on your site's content — whether it's for a web page, article, photo, or other piece of content.
-
-
-
-
- @helper
- Recommendations ([string site],
- [int width],
- [int height],
- [bool showHeader],
- [string colorScheme],
- [string font],
- [string borderColor],
- [string filter],
- [string refLabel])
- No
- Yes
-
-
-
- Shows a Facebook Recommendations plugin. The Recommendations plugin shows personalized recommendations to your users.
-
-
-
-
- @helper
- LikeBox ([string profileId],
- [string name],
- [int width], [int height], [string colorScheme],
- [int connections],
- [bool showStream],
- [bool showHeader])
- No
- No
-
-
-
- Shows a Facebook Like Box. The Like Box is a social plugin that enables Facebook Page owners to attract and gain Likes from their own website.
-
-
-
-
- @helper
- Facepile ([int maxRows],
- [int width])
- Yes
- No
-
-
-
- Shows a Facebook Facepile plugin. The Facepile plugin shows the Facebook profile pictures of the user's friends who have already signed up for your site.
-
-
-
-
- @helper
- LiveStream ([int width],
- [int height],
- [string xid], [string viaUrl], [bool allwaysPostToFriends])
- Yes (only Initialize(...) )
- No
-
-
-
- Shows a Facebook Live Stream plugin. The Live Stream plugin lets users visiting your site or application share activity and comments in real time.
-
-
-
-
- @helper
- ActivityFeed ([string site],
- [int width],
- [int height],
- [bool showHeader],
- [string colorScheme],
- [string font],
- [string borderColor],
- [bool showRecommendations])
- No
- Yes
-
-
-
- Shows a Facebook Activity Feed plugin. The activity feed displays stories both when
- users like content on your site and when users share content from your site back to Facebook.
-
-
-
-
- @helper
- OpenGraphRequiredProperties (string siteName,
-string title,
-string type,
-string url,
-string imageUrl,
- [string description])
- No
- Yes
-
-
-
- OpenGraph properties allows you to specify structured
- information about your web pages to show up your pages richly across Facebook
- and enable Facebook users to establish connections to your pages.
- Use this method to show OpenGraph page data, as the page title, URL, and so on.
-
-
-
-
- @helper
- OpenGraphLocationProperties ([string latitude],
- [string longitude],
-[string streetAddress],
-[string locality],
-[string region],
-[string postalCode],
-[string countryName])
- No
- Yes
-
-
-
- Use this method to show page location data. This is useful if your pages is a business profile or about anything else with a real-world location. You can specify location via latitude and longitude, a full address, or both.
-
-
-
-
- @helper
- OpenGraphContactProperties ([string email],
-[string phoneNumber],
-[string faxNumber])
- No
- Yes
-
-
-
- Use this method to show contact information about your page. Consider including contact information if your page is about an entity that can be contacted.
-
-
-
-
- @helper
- FbmlNamespaces ()
- No
- No
-
-
-
- Use this method inside your opening HTML tag for W3C compatibility.
-
-
-
-
-
-
User Profile Information
-
-
- string Id
- Facebook User Id
-
-
- string Name
- Display Name
-
-
- string First_Name
- First Name
-
-
- string Last_Name
- Last Name
-
-
- string Link
- Link to Profile
-
-
- string Bio
- Short biography
-
-
- string Gender
- Gender
-
-
- string Email
- Published e-mail address
-
-
- string Timezone
- User timezone
-
-
- string Locale
- User regional settings
-
-
- string Updated_Time
- Last updated time on Facebook
-
-
-
-
-
-
-
diff --git a/MyFinance.Web/Facebook/Docs/startHere.htm b/MyFinance.Web/Facebook/Docs/startHere.htm
deleted file mode 100644
index 1185c82..0000000
--- a/MyFinance.Web/Facebook/Docs/startHere.htm
+++ /dev/null
@@ -1,265 +0,0 @@
-
-
-
- Facebook Helper for WebMatrix - Start Here
-
-
-
-
-
-
-
-
-
- Introduction
-
- Microsoft WebMatrix provides an easy way to get started with web development, and
- together with new Razor syntax for ASP.NET Web Pages it includes everything you
- need to get your web site up, running and integrated with many other sites and networks,
- in a short period of time. The WebMatrix helpers are designed to make your life
- easier when creating web sites. They provide you a simple and consistent way of
- performing common web development tasks that otherwise would require a great deal
- of custom coding. With a few lines of code you should be able to secure your web
- site using membership, store information in Windows Azure Storage, integrate your
- site with Facebook, among others things.
-
-
- The Facebook helper is designed to integrate your WebMatrix site
- with Facebook, making it possible to add the
- Facebook Social Plugins , such as Like button, Facepile, Comments, Login
- Button and Like Box, among others, in a few simple steps. It also allows you easily
- integrate your site with the Facebook login mechanism, so users do not have to create
- another account just to access your website.
-
-
- Depending on the social plugin you want to use, the helper requires that you call
- an initialization method. Check the table below and if the social plugin you want
- to use does not require initialization see the Getting Started in 60 seconds
- (without initialization) section, otherwise see the Getting Started
- in 60 seconds (with initialization) section.
-
-
-
-
-
- Social Plugin
-
-
- Initialization Required
-
-
-
-
-
-
- Like Button
-
-
- No
-
-
-
-
- Activity Feed
-
-
- No
-
-
-
-
- Recommendations
-
-
- No
-
-
-
-
- Like Box
-
-
- No
-
-
-
-
- Login Button
-
-
- Yes
-
-
-
-
- Facepile
-
-
- Yes
-
-
-
-
- Comments
-
-
- Yes
-
-
-
-
- Live Stream
-
-
- Yes
-
-
-
-
-
- Getting Started in 60 Seconds (without initialization)
-
- These steps will guide you on how to display a Facebook Like button into your Web
- site:
-
-
- Add the highlighted line from below in the page where you want to show the Like
- button, in this case for liking the Microsoft Web home page:
-
- <!DOCTYPE html>
- <html>
- ...
- <body>
- ...
- @Facebook.LikeButton("http://www.microsoft.com/web")
- ...
- </body>
- </html>
-
-
-
-
- Getting Started in 60 Seconds (with initialization)
-
- These steps will guide you on how to display a Facebook Comments box into your Web
- site:
-
-
- Make note of the Site URL where your Microsoft WebMatrix site is
- running (click the Site workspace | Settings page).
-
-
- Register a new Facebook
- application and make note of the Application Id and Secret. (Check
- http://www.facebook.com/developers for instructions on how to create a Facebook
- application).
-
-
-
-
- When creating your Facebook application, make sure you set the Site Url to
- http://localhost:[port] , replacing the [port] placeholder with
- the port where your local WebMatrix site is running.
-
-
-
-
- Add the following line to the _AppStart.cshtml page of your WebMatrix
- Site (create this page if it does not exist). Replace the placeholders with your
- Application Id and Secret.
-
- @{
- Facebook.Initialize("{your App ID}", "{your
- App Secret}");
- }
-
-
- Add the highlighted lines from below in the page where you want to show the Comments
- box:
-
- <!DOCTYPE html>
- <html @Facebook.FbmlNamespaces() >
- ...
- <body>
- @Facebook.GetInitializationScripts()
- ...
- @Facebook.Comments()
- ...
- </body>
- </html>
-
-
-
-
-
Note: Some of the Facebook Social Plugins require that your site
- is published into a public address where others can use it; see the
- helper reference for a complete list. To do this you can try some of the
- *Free* WebMatrix Hostings providers, like
Cytanium
- (also check this tutorial on
- publishing with WebMatrix) .
-
- Running the Facebook Helper Sample
-
- Optionally, you can download a sample WebMatrix web site where you can see the helper
- in action, and also see how to use the helper to integrate the Facebook login
- mechanism with the membership model of your web site . To download and
- run it with Microsoft WebMatrix, follow these steps:
-
- Browse to the Facebook Helper CodePlex
- site and download the Facebook Helper Sample
- Extract the content of the package, right-click the Facebook.Bakery
- folder and select 'Open as a Web Site with Microsoft WebMatrix'. This will open
- the Bakery sample web site with WebMatrix.
- Change your WebMatrix site settings to match the Site Url you have
- configured in your Facebook application settings.
-
-
-
-
- Open the _AppStart.cshtml page, uncomment the following line and
- replace the placeholders with your Facebook Application Id and Secret.
-
- @{
- Facebook.Initialize("{your App ID}", "{your
- App Secret}", "bakery");
- ...
- }
-
-
- Click on the Run button located in the Home tab.
- Play with the sample!
-
-
- More Info
-
- The helper ships with the following files: The Facebook.cshtml
- file located into the App_Code folder inside you WebMatrix site,
- and a Login.cshtml file under the Facebook folder
- that will handle user login when using his Facebook account.
-
-
- Learn more on WebMatrix, ASP.NET Web Pages and the Razor Syntax
- with the WebMatrix tutorials .
-
-
- To explore the helper implementation you can open the Facebook.cshtml
- file located under the App_Code folder. Additionally, you can get
- more information on the helper from the
- Facebook Helper CodePlex site .
-
-
-
-
-
-
diff --git a/MyFinance.Web/Facebook/Login.cshtml b/MyFinance.Web/Facebook/Login.cshtml
deleted file mode 100644
index 62c383f..0000000
--- a/MyFinance.Web/Facebook/Login.cshtml
+++ /dev/null
@@ -1,11 +0,0 @@
-@{
- if (!Facebook.IsFacebookUserAuthenticated) {
- Response.Redirect("~/");
- }
-
- if (Facebook.MembershipLogin()) {
- Context.RedirectLocal(Request["returnUrl"]);
- } else {
- Context.RedirectLocal(Request["registerUrl"]);
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Global.asax b/MyFinance.Web/Global.asax
deleted file mode 100644
index 29c4aec..0000000
--- a/MyFinance.Web/Global.asax
+++ /dev/null
@@ -1 +0,0 @@
-<%@ Application Codebehind="Global.asax.cs" Inherits="MyFinance.Web.MvcApplication" Language="C#" %>
diff --git a/MyFinance.Web/Global.asax.cs b/MyFinance.Web/Global.asax.cs
deleted file mode 100644
index 5d4caee..0000000
--- a/MyFinance.Web/Global.asax.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using System.Web.Routing;
-using Microsoft.Practices.Unity;
-using MyFinance.Web.Models;
-using System.Web.Security;
-using MyFinance.Web.IoC;
-using MyFinance.Data;
-using MyFinance.Data.Infrastructure;
-using MyFinance.Domain;
-using MyFinance.Web.ViewModel;
-using MyFinance.Service;
-using MyFinance.Web.Controllers;
-using MyFinance.Web.Helpers;
-using System.Data.Entity;
-namespace MyFinance.Web
-{
- // Note: For instructions on enabling IIS6 or IIS7 classic mode,
- // visit http://go.microsoft.com/?LinkId=9394801
-
- public class MvcApplication : System.Web.HttpApplication
- {
- public static void RegisterGlobalFilters(GlobalFilterCollection filters)
- {
- filters.Add(new HandleErrorAttribute());
- }
-
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- routes.IgnoreRoute("elmah.axd");
- routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
-
- routes.MapRoute(
- "Default", // Route name
- "{controller}/{action}/{id}", // URL with parameters
- new { controller = "Home", action = "Index", id = UrlParameter.Optional },// Parameter defaults
- new[] { "MyFinance.Web.Controllers" }
- );
-
- }
-
-protected void Application_Start()
-{
- AreaRegistration.RegisterAllAreas();
- // Initializes and seeds the database.
- Database.SetInitializer(new MyFinanceContextInitializer());
- GlobalFilters.Filters.Add(new RedirectMobileDevicesToMobileAreaAttribute(), 1);
- RegisterGlobalFilters(GlobalFilters.Filters);
- RegisterRoutes(RouteTable.Routes);
- IUnityContainer container = GetUnityContainer();
- DependencyResolver.SetResolver(new UnityDependencyResolver(container));
-}
-
- private IUnityContainer GetUnityContainer()
- {
- //Create UnityContainer
- IUnityContainer container = new UnityContainer()
- //.RegisterType() // No nned to a controller activator
- .RegisterType()
- .RegisterType()
- .RegisterInstance(Membership.Provider)
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager())
- .RegisterType(new HttpContextLifetimeManager());
- return container;
- }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Helpers/DatePickerHelper.cs b/MyFinance.Web/Helpers/DatePickerHelper.cs
deleted file mode 100644
index 1d446d7..0000000
--- a/MyFinance.Web/Helpers/DatePickerHelper.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using System.Threading;
-
-namespace MyFinance.Helpers
-{
- public static class DatePickerHelper
- {
- public static string DatePicker(this HtmlHelper htmlHelper, string name, string value)
- {
-
- return "" +
- " ";
-
- }
-
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Helpers/HandleErrorWithELMAHAttribute .cs b/MyFinance.Web/Helpers/HandleErrorWithELMAHAttribute .cs
deleted file mode 100644
index 1163e74..0000000
--- a/MyFinance.Web/Helpers/HandleErrorWithELMAHAttribute .cs
+++ /dev/null
@@ -1,58 +0,0 @@
-//using System;
-//using System.Collections.Generic;
-//using System.Linq;
-//using System.Web;
-//using System.Web.Mvc;
-//using System.Diagnostics;
-
-//namespace MyFinance.Helpers
-//{
-// //From http://stackoverflow.com/questions/766610/
-// public class HandleErrorWithELMAHAttribute : HandleErrorAttribute
-// {
-// public override void OnException(ExceptionContext context)
-// {
-// base.OnException(context);
-
-// var e = context.Exception;
-// if (!context.ExceptionHandled // if unhandled, will be logged anyhow
-// || RaiseErrorSignal(e) // prefer signaling, if possible
-// || IsFiltered(context)) // filtered?
-// return;
-
-// LogException(e);
-// }
-
-// private static bool RaiseErrorSignal(Exception e)
-// {
-// var context = HttpContext.Current;
-// if (context == null)
-// return false;
-// var signal = ErrorSignal.FromContext(context);
-// if (signal == null)
-// return false;
-// signal.Raise(e, context);
-// return true;
-// }
-
-// private static bool IsFiltered(ExceptionContext context)
-// {
-// var config = context.HttpContext.GetSection("elmah/errorFilter")
-// as ErrorFilterConfiguration;
-
-// if (config == null)
-// return false;
-
-// var testContext = new ErrorFilterModule.AssertionHelperContext(
-// context.Exception, HttpContext.Current);
-
-// return config.Assertion.Test(testContext);
-// }
-
-// private static void LogException(Exception e)
-// {
-// var context = HttpContext.Current;
-// ErrorLog.GetDefault(context).Log(new Error(e, context));
-// }
-// }
-//}
diff --git a/MyFinance.Web/Helpers/RedirectMobileDevicesToMobileAreaAttribute.cs b/MyFinance.Web/Helpers/RedirectMobileDevicesToMobileAreaAttribute.cs
deleted file mode 100644
index 218c53e..0000000
--- a/MyFinance.Web/Helpers/RedirectMobileDevicesToMobileAreaAttribute.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using System.Web.Mvc;
-using System.Web.Routing;
-namespace MyFinance.Web.Helpers
-{
- //The class is taken from http://aspnetmobilesamples.codeplex.com/
- public class RedirectMobileDevicesToMobileAreaAttribute : AuthorizeAttribute
- {
- protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
- {
- // Only redirect on the first request in a session
- if (!httpContext.Session.IsNewSession)
- return true;
-
- // Don't redirect non-mobile browsers
- if (!httpContext.Request.Browser.IsMobileDevice)
- return true;
-
- // Don't redirect requests for the Mobile area
- if (Regex.IsMatch(httpContext.Request.Url.PathAndQuery, "/Mobile($|/)"))
- return true;
-
- return false;
- }
-
- protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
- {
- var redirectionRouteValues = GetRedirectionRouteValues(filterContext.RequestContext);
- filterContext.Result = new RedirectToRouteResult(redirectionRouteValues);
- }
-
- // Override this method if you want to customize the controller/action/parameters to which
- // mobile users would be redirected. This lets you redirect users to the mobile equivalent
- // of whatever resource they originally requested.
- protected virtual RouteValueDictionary GetRedirectionRouteValues(RequestContext requestContext)
- {
- return new RouteValueDictionary(new { area = "Mobile", controller = "Home", action = "Index" });
- }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/IoC/CustomControllerActivator.cs b/MyFinance.Web/IoC/CustomControllerActivator.cs
deleted file mode 100644
index 09c1d8f..0000000
--- a/MyFinance.Web/IoC/CustomControllerActivator.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-namespace MyFinance.Web.IoC
-{
- public class CustomControllerActivator : IControllerActivator
- {
- IController IControllerActivator.Create(
- System.Web.Routing.RequestContext requestContext,
- Type controllerType)
- {
- return DependencyResolver.Current
- .GetService(controllerType) as IController;
- }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/IoC/UnityControllerFactory .cs b/MyFinance.Web/IoC/UnityControllerFactory .cs
deleted file mode 100644
index bbd95fa..0000000
--- a/MyFinance.Web/IoC/UnityControllerFactory .cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using System.Web.Routing;
-using Microsoft.Practices.Unity;
-using System.Web.SessionState;
-
-namespace MyFinance.Web.IoC
-{
- public class UnityControllerFactory : DefaultControllerFactory
- {
- IUnityContainer container;
- public UnityControllerFactory(IUnityContainer container)
- {
- this.container = container;
- }
- protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
- {
- IController controller;
- if (controllerType == null)
- throw new HttpException(
- 404, String.Format(
- "The controller for path '{0}' could not be found" +
- "or it does not implement IController.",
- reqContext.HttpContext.Request.Path));
-
- if (!typeof(IController).IsAssignableFrom(controllerType))
- throw new ArgumentException(
- string.Format(
- "Type requested is not a controller: {0}",
- controllerType.Name),
- "controllerType");
- try
- {
- //controller = MvcUnityContainer.Container.Resolve(controllerType)
- // as IController;
- controller= container.Resolve(controllerType) as IController;
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(String.Format(
- "Error resolving controller {0}",
- controllerType.Name), ex);
- }
- return controller;
- }
-
- }
- public class HttpContextLifetimeManager : LifetimeManager, IDisposable
- {
- public override object GetValue()
- {
- return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
- }
- public override void RemoveValue()
- {
- HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
- }
- public override void SetValue(object newValue)
- {
- HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
- }
- public void Dispose()
- {
- RemoveValue();
- }
- }
-}
\ No newline at end of file
diff --git a/MyFinance.Web/IoC/UnityDependencyResolver.cs b/MyFinance.Web/IoC/UnityDependencyResolver.cs
deleted file mode 100644
index b83d0a6..0000000
--- a/MyFinance.Web/IoC/UnityDependencyResolver.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using Microsoft.Practices.Unity;
-
-namespace MyFinance.Web.IoC
-{
-public class UnityDependencyResolver : IDependencyResolver
-{
- IUnityContainer container;
- public UnityDependencyResolver(IUnityContainer container)
- {
- this.container = container;
- }
-
- public object GetService(Type serviceType)
- {
- try
- {
- return container.Resolve(serviceType);
- }
- catch
- {
- return null;
- }
- }
-
- public IEnumerable GetServices(Type serviceType)
- {
- try
- {
- return container.ResolveAll(serviceType);
- }
- catch
- {
- return new List();
- }
- }
-}
-}
\ No newline at end of file
diff --git a/MyFinance.Web/Models/AccountModels.cs b/MyFinance.Web/Models/AccountModels.cs
deleted file mode 100644
index 8a67fe1..0000000
--- a/MyFinance.Web/Models/AccountModels.cs
+++ /dev/null
@@ -1,251 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.ComponentModel.DataAnnotations;
-using System.Globalization;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-using System.Web.Security;
-
-namespace MyFinance.Web.Models
-{
-
- #region Models
-
- public class ChangePasswordModel
- {
- [Required]
- [DataType(DataType.Password)]
- [Display(Name = "Current password")]
- public string OldPassword { get; set; }
-
- [Required]
- [ValidatePasswordLength]
- [DataType(DataType.Password)]
- [Display(Name = "New password")]
- public string NewPassword { get; set; }
-
- [DataType(DataType.Password)]
- [Display(Name = "Confirm new password")]
- [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
- public string ConfirmPassword { get; set; }
- }
-
- public class LogOnModel
- {
- [Required]
- [Display(Name = "User name")]
- public string UserName { get; set; }
-
- [Required]
- [DataType(DataType.Password)]
- [Display(Name = "Password")]
- public string Password { get; set; }
-
- [Display(Name = "Remember me?")]
- public bool RememberMe { get; set; }
- }
-
-
- public class RegisterModel
- {
- [Required]
- [Display(Name = "User name")]
- public string UserName { get; set; }
-
- [Required]
- [DataType(DataType.EmailAddress)]
- [Display(Name = "Email address")]
- public string Email { get; set; }
-
- [Required]
- [ValidatePasswordLength]
- [DataType(DataType.Password)]
- [Display(Name = "Password")]
- public string Password { get; set; }
-
- [DataType(DataType.Password)]
- [Display(Name = "Confirm password")]
- [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
- public string ConfirmPassword { get; set; }
- }
- #endregion
-
- #region Services
- // The FormsAuthentication type is sealed and contains static members, so it is difficult to
- // unit test code that calls its members. The interface and helper class below demonstrate
- // how to create an abstract wrapper around such a type in order to make the AccountController
- // code unit testable.
-
- public interface IMembershipService
- {
- int MinPasswordLength { get; }
-
- bool ValidateUser(string userName, string password);
- MembershipCreateStatus CreateUser(string userName, string password, string email);
- bool ChangePassword(string userName, string oldPassword, string newPassword);
- }
-
- public class AccountMembershipService : IMembershipService
- {
- private readonly MembershipProvider _provider;
-
- public AccountMembershipService()
- : this(null)
- {
- }
-
- public AccountMembershipService(MembershipProvider provider)
- {
- _provider = provider ?? Membership.Provider;
- }
-
- public int MinPasswordLength
- {
- get
- {
- return _provider.MinRequiredPasswordLength;
- }
- }
-
- public bool ValidateUser(string userName, string password)
- {
- if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
- if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
-
- return _provider.ValidateUser(userName, password);
- }
-
- public MembershipCreateStatus CreateUser(string userName, string password, string email)
- {
- if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
- if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
- if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
-
- MembershipCreateStatus status;
- _provider.CreateUser(userName, password, email, null, null, true, null, out status);
- return status;
- }
-
- public bool ChangePassword(string userName, string oldPassword, string newPassword)
- {
- if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
- if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
- if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");
-
- // The underlying ChangePassword() will throw an exception rather
- // than return false in certain failure scenarios.
- try
- {
- MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */);
- return currentUser.ChangePassword(oldPassword, newPassword);
- }
- catch (ArgumentException)
- {
- return false;
- }
- catch (MembershipPasswordException)
- {
- return false;
- }
- }
- }
-
- public interface IFormsAuthenticationService
- {
- void SignIn(string userName, bool createPersistentCookie);
- void SignOut();
- }
-
- public class FormsAuthenticationService : IFormsAuthenticationService
- {
- public void SignIn(string userName, bool createPersistentCookie)
- {
- if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
-
- FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
- }
-
- public void SignOut()
- {
- FormsAuthentication.SignOut();
- }
- }
- #endregion
-
- #region Validation
- public static class AccountValidation
- {
- public static string ErrorCodeToString(MembershipCreateStatus createStatus)
- {
- // See http://go.microsoft.com/fwlink/?LinkID=177550 for
- // a full list of status codes.
- switch (createStatus)
- {
- case MembershipCreateStatus.DuplicateUserName:
- return "Username already exists. Please enter a different user name.";
-
- case MembershipCreateStatus.DuplicateEmail:
- return "A username for that e-mail address already exists. Please enter a different e-mail address.";
-
- case MembershipCreateStatus.InvalidPassword:
- return "The password provided is invalid. Please enter a valid password value.";
-
- case MembershipCreateStatus.InvalidEmail:
- return "The e-mail address provided is invalid. Please check the value and try again.";
-
- case MembershipCreateStatus.InvalidAnswer:
- return "The password retrieval answer provided is invalid. Please check the value and try again.";
-
- case MembershipCreateStatus.InvalidQuestion:
- return "The password retrieval question provided is invalid. Please check the value and try again.";
-
- case MembershipCreateStatus.InvalidUserName:
- return "The user name provided is invalid. Please check the value and try again.";
-
- case MembershipCreateStatus.ProviderError:
- return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
-
- case MembershipCreateStatus.UserRejected:
- return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
-
- default:
- return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
- }
- }
- }
-
- [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
- public sealed class ValidatePasswordLengthAttribute : ValidationAttribute, IClientValidatable
- {
- private const string _defaultErrorMessage = "'{0}' must be at least {1} characters long.";
- private readonly int _minCharacters = Membership.Provider.MinRequiredPasswordLength;
-
- public ValidatePasswordLengthAttribute()
- : base(_defaultErrorMessage)
- {
- }
-
- public override string FormatErrorMessage(string name)
- {
- return String.Format(CultureInfo.CurrentCulture, ErrorMessageString,
- name, _minCharacters);
- }
-
- public override bool IsValid(object value)
- {
- string valueAsString = value as string;
- return (valueAsString != null && valueAsString.Length >= _minCharacters);
- }
-
- public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
- {
- return new[]{
- new ModelClientValidationStringLengthRule(FormatErrorMessage(metadata.GetDisplayName()), _minCharacters, int.MaxValue)
- };
- }
- }
- #endregion
-
-}
diff --git a/MyFinance.Web/MyFinance.Web.csproj b/MyFinance.Web/MyFinance.Web.csproj
deleted file mode 100644
index e62c507..0000000
--- a/MyFinance.Web/MyFinance.Web.csproj
+++ /dev/null
@@ -1,300 +0,0 @@
-
-
-
- Debug
- AnyCPU
-
-
- 2.0
- {FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}
- {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
- Library
- Properties
- MyFinance.Web
- MyFinance.Web
- v4.0
- false
-
-
-
-
-
-
-
-
- false
-
-
- true
- full
- false
- bin\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\Altairis.Web.Security.2.4.0\lib\net40\Altairis.Web.Security.dll
-
-
- False
- ..\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll
-
-
- ..\packages\51Degrees.mobi.0.1.11.11\lib\NET40\FiftyOne.Foundation.dll
-
-
-
- ..\packages\Unity.2.0\lib\20\Microsoft.Practices.ServiceLocation.dll
-
-
- ..\packages\Unity.2.0\lib\20\Microsoft.Practices.Unity.dll
-
-
- ..\packages\Unity.2.0\lib\20\Microsoft.Practices.Unity.Configuration.dll
-
-
- ..\packages\Unity.2.0\lib\20\Microsoft.Practices.Unity.Interception.dll
-
-
- ..\packages\Unity.2.0\lib\20\Microsoft.Practices.Unity.Interception.Configuration.dll
-
-
- ..\packages\microsoft-web-helpers.1.1\lib\Microsoft.Web.Helpers.dll
-
-
- False
- ..\packages\MicrosoftWebMvc.2.0\lib\Microsoft.Web.Mvc.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\packages\WebActivator.1.0.0.0\lib\WebActivator.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Global.asax
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
- Web.config
-
-
- Web.config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}
- MyFinance.Data
-
-
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}
- MyFinance.Domain
-
-
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}
- MyFinance.Service
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
- True
- 38994
- /
-
-
- False
- False
-
-
- False
-
-
-
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/Scripts/jquery-1.4.4.min.js b/MyFinance.Web/Scripts/jquery-1.4.4.min.js
deleted file mode 100644
index 7015ffd..0000000
--- a/MyFinance.Web/Scripts/jquery-1.4.4.min.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/*!
- * Note: While Microsoft is not the author of this file, Microsoft is
- * offering you a license subject to the terms of the Microsoft Software
- * License Terms for Microsoft ASP.NET Model View Controller 3.
- * Microsoft reserves all other rights. The notices below are provided
- * for informational purposes only and are not the license terms under
- * which Microsoft distributed this file.
- *
- * jQuery JavaScript Library v1.4.4
- * http://jquery.com/
- *
- * Copyright 2010, John Resig
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2010, The Dojo Foundation
- *
- * Date: Thu Nov 11 19:04:53 2010 -0500
- */
-(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
-h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
-"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
-e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
-"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
-a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
-C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
-s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
-j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
-toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
--1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
-if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
-b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
-!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
-l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;Ha ";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
-k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
-scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
-false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML=" ";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
-1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
-"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
-c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
-else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
-if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
-attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
-b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
-c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
-arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
-d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
-c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
-8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
-"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
-d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
-B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
-"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
-0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
-(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
-break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
-q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
-l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
-m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
-true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
-g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]-
-0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
-i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
-if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
-g);else if(typeof g.length==="number")for(var p=g.length;n
";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
-n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML=" ";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
-function(){var g=k,i=t.createElement("div");i.innerHTML="
";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
-p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
-t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
-function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
-h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
-c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
-2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
-b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
-e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1,
-""," "],legend:[1,""," "],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""," "],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
-c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
-wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
-prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
-this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
-return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
-else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>$2>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
-prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
-b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length-
-1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
-d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
-jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
-zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
-h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
-if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
-d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
-e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/
-
-
-@using (Html.BeginForm()) {
- @Html.ValidationSummary(true)
-
- Category
- @Html.EditorFor(model => model)
-
-
-
-
-}
-
-
- @Html.ActionLink("Back to List", "Index")
-
-
diff --git a/MyFinance.Web/Views/Category/Edit.cshtml b/MyFinance.Web/Views/Category/Edit.cshtml
deleted file mode 100644
index 7d6bd7a..0000000
--- a/MyFinance.Web/Views/Category/Edit.cshtml
+++ /dev/null
@@ -1,29 +0,0 @@
-@model MyFinance.Domain.Category
-
-@{
- ViewBag.Title = "Edit";
-}
-
-Edit Category
-
-
-
-
-@using (Html.BeginForm()) {
- @Html.ValidationSummary(true)
-
- Category
-
- @Html.HiddenFor(model => model.CategoryId)
- @Html.EditorFor(model => model)
-
-
-
-
-
-}
-
-
- @Html.ActionLink("Back to List", "Index")
-
-
diff --git a/MyFinance.Web/Views/Category/Index.cshtml b/MyFinance.Web/Views/Category/Index.cshtml
deleted file mode 100644
index 0ea9426..0000000
--- a/MyFinance.Web/Views/Category/Index.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model IEnumerable
-@{
- ViewBag.Title = "Index";
-}
-Category List
-
-
- @Html.Partial("CategoryList", Model)
-
diff --git a/MyFinance.Web/Views/Home/Index.cshtml b/MyFinance.Web/Views/Home/Index.cshtml
deleted file mode 100644
index 6f16e21..0000000
--- a/MyFinance.Web/Views/Home/Index.cshtml
+++ /dev/null
@@ -1,8 +0,0 @@
-@{
- ViewBag.Title = "Home Page";
-}
-
-
- A demo web app using ASP.NET MVC 3 RTM, Razor, EF Code First and Unity 2.0.
-
-@*
*@
\ No newline at end of file
diff --git a/MyFinance.Web/Views/Shared/EditorTemplates/Category.cshtml b/MyFinance.Web/Views/Shared/EditorTemplates/Category.cshtml
deleted file mode 100644
index 40090d5..0000000
--- a/MyFinance.Web/Views/Shared/EditorTemplates/Category.cshtml
+++ /dev/null
@@ -1,16 +0,0 @@
-@model MyFinance.Domain.Category
-
-@Html.LabelFor(model => model.Name)
-
-
-@Html.EditorFor(model => model.Name)
-@Html.ValidationMessageFor(model => model.Name)
-
-
-
-@Html.LabelFor(model => model.Description)
-
-
-@Html.EditorFor(model => model.Description)
-@Html.ValidationMessageFor(model => model.Description)
-
diff --git a/MyFinance.Web/Views/Shared/Error.cshtml b/MyFinance.Web/Views/Shared/Error.cshtml
deleted file mode 100644
index 8ee384b..0000000
--- a/MyFinance.Web/Views/Shared/Error.cshtml
+++ /dev/null
@@ -1,9 +0,0 @@
-@model System.Web.Mvc.HandleErrorInfo
-
-@{
- ViewBag.Title = "Error";
-}
-
-
- Sorry, an error occurred while processing your request.
-
diff --git a/MyFinance.Web/Views/Shared/PermissionDenied.cshtml b/MyFinance.Web/Views/Shared/PermissionDenied.cshtml
deleted file mode 100644
index 448ef44..0000000
--- a/MyFinance.Web/Views/Shared/PermissionDenied.cshtml
+++ /dev/null
@@ -1,6 +0,0 @@
-@{
- ViewBag.Title = "PermissionDenied";
-}
-
-PermissionDenied
-Sorry, you don't have enough rights to continue.
diff --git a/MyFinance.Web/Views/Shared/_Layout.cshtml b/MyFinance.Web/Views/Shared/_Layout.cshtml
deleted file mode 100644
index 6adf7f7..0000000
--- a/MyFinance.Web/Views/Shared/_Layout.cshtml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
- @ViewBag.Title
-
-
-
-
-
-
-
-
-
-
- @RenderBody()
-
-
-
-
-
diff --git a/MyFinance.Web/Web.config b/MyFinance.Web/Web.config
deleted file mode 100644
index 25074b6..0000000
--- a/MyFinance.Web/Web.config
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MyFinance.Web/packages.config b/MyFinance.Web/packages.config
deleted file mode 100644
index 4609761..0000000
--- a/MyFinance.Web/packages.config
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MyFinance.sln b/MyFinance.sln
deleted file mode 100644
index f2b1a2a..0000000
--- a/MyFinance.sln
+++ /dev/null
@@ -1,38 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFinance.Data", "MyFinance.Data\MyFinance.Data.csproj", "{A9F879BC-CA11-4470-A655-8541B5DA41A1}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFinance.Domain", "MyFinance.Domain\MyFinance.Domain.csproj", "{48F672E8-4513-4F7E-A296-C0CCC87F9AA1}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFinance.Web", "MyFinance.Web\MyFinance.Web.csproj", "{FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFinance.Service", "MyFinance.Service\MyFinance.Service.csproj", "{BA69BB65-147A-42D8-A6F5-5D1E57E2D783}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A9F879BC-CA11-4470-A655-8541B5DA41A1}.Release|Any CPU.Build.0 = Release|Any CPU
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {48F672E8-4513-4F7E-A296-C0CCC87F9AA1}.Release|Any CPU.Build.0 = Release|Any CPU
- {FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FE22D839-09AA-4DE8-BAF7-E29C6EB2EECC}.Release|Any CPU.Build.0 = Release|Any CPU
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BA69BB65-147A-42D8-A6F5-5D1E57E2D783}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000..f3bd58a
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,13 @@
+Required Frameworks
+--------------------------------------
+
+1. .NET 4.5
+2. ASP.NET MVC 4
+3. Entity Framework 5 Code First
+4. Windows Azure SDK
+5. Autofac
+6. AutoMapper
+7. NUnit
+8. Moq
+
+