diff --git a/.hgsub b/.hgsub index d3f5a12fa..3bb7e7f36 100644 --- a/.hgsub +++ b/.hgsub @@ -1 +1,5 @@ +src/Orchard.Web/Modules/Orchard.Forms = https://hg01.codeplex.com/orchardforms +src/Orchard.Web/Modules/Orchard.Rules = https://hg01.codeplex.com/orchardrules +src/Orchard.Web/Modules/Orchard.Tokens = https://hg01.codeplex.com/orchardtokens +src/Orchard.Web/Modules/Orchard.TaskLease = https://hg01.codeplex.com/orchardtasklease \ No newline at end of file diff --git a/.hgsubstate b/.hgsubstate index e69de29bb..338f554f5 100644 --- a/.hgsubstate +++ b/.hgsubstate @@ -0,0 +1,4 @@ +d9555c4ed3edaea5f4bd8cb90685ea1c663a9e1c src/Orchard.Web/Modules/Orchard.Forms +7eeb2b10fe65f82f69096ac1cb5cbfa9d861e542 src/Orchard.Web/Modules/Orchard.Rules +7c6d6b4f2d695dd8ec23d6f3062334303082a78a src/Orchard.Web/Modules/Orchard.TaskLease +3d8ff35c6f8cd1b86b084cb689d8a1f48e2f77c1 src/Orchard.Web/Modules/Orchard.Tokens diff --git a/AzurePackage.proj b/AzurePackage.proj index ecb02feb0..b2d984895 100644 --- a/AzurePackage.proj +++ b/AzurePackage.proj @@ -14,17 +14,19 @@ $(ServiceFolder)\roles\Orchard.Azure.Web\approot $(CompileFolder)\_PublishedWebsites $(BuildFolder)\Stage + $(SrcFolder)\Orchard.Azure\Orchard.Azure.Web\obj\Release\Package\PackageTmp + - - + + - + @@ -47,19 +49,23 @@ + + + - + Properties="Configuration=Release;DeployOnBuild=true;DeployTarget=Package;PlatformTarget=x64" + /> + + Properties="Configuration=Release;OutputPath=$(MsDeployFolder)\bin;PlatformTarget=x64" + /> @@ -72,7 +78,7 @@ - + @@ -80,39 +86,54 @@ + - + + + - - - - - + + + + + - + - - - - @@ -133,14 +154,14 @@ - - + + diff --git a/Orchard.proj b/Orchard.proj index f07bc8a5b..396137df6 100644 --- a/Orchard.proj +++ b/Orchard.proj @@ -47,8 +47,8 @@ + - @@ -378,6 +378,10 @@ + + + + diff --git a/lib/claysharp/ClaySharp.dll b/lib/claysharp/ClaySharp.dll index a5e194cef..51179ddad 100644 Binary files a/lib/claysharp/ClaySharp.dll and b/lib/claysharp/ClaySharp.dll differ diff --git a/lib/claysharp/ClaySharp.pdb b/lib/claysharp/ClaySharp.pdb new file mode 100644 index 000000000..991b7fc80 Binary files /dev/null and b/lib/claysharp/ClaySharp.pdb differ diff --git a/lib/markdown/MarkdownSharp.dll b/lib/markdown/MarkdownSharp.dll new file mode 100644 index 000000000..b779a466b Binary files /dev/null and b/lib/markdown/MarkdownSharp.dll differ diff --git a/lib/markdown/MarkdownSharp.pdb b/lib/markdown/MarkdownSharp.pdb new file mode 100644 index 000000000..a6695c63c Binary files /dev/null and b/lib/markdown/MarkdownSharp.pdb differ diff --git a/lib/markdown/MarkdownSharp.xml b/lib/markdown/MarkdownSharp.xml new file mode 100644 index 000000000..e76600659 --- /dev/null +++ b/lib/markdown/MarkdownSharp.xml @@ -0,0 +1,433 @@ + + + + MarkdownSharp + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + + Markdown is a text-to-HTML conversion tool for web writers. + Markdown allows you to write using an easy-to-read, easy-to-write plain text format, + then convert it to structurally valid XHTML (or HTML). + + + + + maximum nested depth of [] and () supported by the transform; implementation detail + + + + + Tabs are automatically converted to spaces as part of the transform + this constant determines how "wide" those tabs become in spaces + + + + + Create a new Markdown instance using default options + + + + + Create a new Markdown instance and optionally load options from the supplied options parameter. + + + + + Create a new Markdown instance and optionally load options from a configuration + file. There they should be stored in the appSettings section, available options are: + + Markdown.StrictBoldItalic (true/false) + Markdown.EmptyElementSuffix (">" or " />" without the quotes) + Markdown.LinkEmails (true/false) + Markdown.AutoNewLines (true/false) + Markdown.AutoHyperlink (true/false) + Markdown.EncodeProblemUrlCharacters (true/false) + + + + + In the static constuctor we'll initialize what stays the same across all transforms. + + + + + Transforms the provided Markdown-formatted text to HTML; + see http://en.wikipedia.org/wiki/Markdown + + + The order in which other subs are called here is + essential. Link and image substitutions need to happen before + EscapeSpecialChars(), so that any *'s or _'s in the a + and img tags get encoded. + + + + + Perform transformations that form block-level tags like paragraphs, headers, and list items. + + + + + Perform transformations that occur *within* block-level tags like paragraphs, headers, and list items. + + + + + splits on two or more newlines, to form "paragraphs"; + each paragraph is then unhashed (if it is a hash) or wrapped in HTML p tag + + + + + Reusable pattern to match balanced [brackets]. See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Reusable pattern to match balanced (parens). See Friedl's + "Mastering Regular Expressions", 2nd Ed., pp. 328-331. + + + + + Strips link definitions from text, stores the URLs and titles in hash references. + + + ^[id]: url "optional title" + + + + + derived pretty much verbatim from PHP Markdown + + + + + replaces any block-level HTML blocks with hash entries + + + + + returns an array of HTML tokens comprising the input string. Each token is + either a tag (possibly with nested, tags contained therein, such + as <a href="<MTFoo>">, or a run of text between tags. Each element of the + array is a two-element array; the first is either 'tag' or 'text'; the second is + the actual value. + + + + + Turn Markdown link shortcuts into HTML anchor tags + + + [link text](url "title") + [link text][id] + [id] + + + + + Turn Markdown image shortcuts into HTML img tags. + + + ![alt text][id] + ![alt text](url "optional title") + + + + + Turn Markdown headers into HTML header tags + + + Header 1 + ======== + + Header 2 + -------- + + # Header 1 + ## Header 2 + ## Header 2 with closing hashes ## + ... + ###### Header 6 + + + + + Turn Markdown horizontal rules into HTML hr tags + + + *** + * * * + --- + - - - + + + + + Turn Markdown lists into HTML ul and ol and li tags + + + + + Process the contents of a single ordered or unordered list, splitting it + into individual list items. + + + + + /// Turn Markdown 4-space indented code into HTML pre code blocks + + + + + Turn Markdown `code spans` into HTML code tags + + + + + Turn Markdown *italics* and **bold** into HTML strong and em tags + + + + + Turn markdown line breaks (two space at end of line) into HTML break tags + + + + + Turn Markdown > quoted blocks into HTML blockquote blocks + + + + + Turn angle-delimited URLs into HTML anchor tags + + + <http://www.example.com> + + + + + Remove one level of line-leading spaces + + + + + encodes email address randomly + roughly 10% raw, 45% hex, 45% dec + note that @ is always encoded and : never is + + + + + Encode/escape certain Markdown characters inside code blocks and spans where they are literals + + + + + Encode any ampersands (that aren't part of an HTML entity) and left or right angle brackets + + + + + Encodes any escaped characters such as \`, \*, \[ etc + + + + + swap back in all the special characters we've hidden + + + + + escapes Bold [ * ] and Italic [ _ ] characters + + + + + hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems + + + + + Within tags -- meaning between < and > -- encode [\ ` * _] so they + don't conflict with their use in Markdown for code, italics and strong. + We're replacing each such character with its corresponding hash + value; this is likely overkill, but it should prevent us from colliding + with the escape values by accident. + + + + + convert all tabs to _tabWidth spaces; + standardizes line endings from DOS (CR LF) or Mac (CR) to UNIX (LF); + makes sure text ends with a couple of newlines; + removes any blank lines (only spaces) in the text + + + + + this is to emulate what's evailable in PHP + + + + + current version of MarkdownSharp; + see http://code.google.com/p/markdownsharp/ for the latest code or to contribute + + + + + Static constructor + + + In the static constuctor we'll initialize what stays the same across all transforms. + + + + + + Strips link definitions from text, stores the URLs and titles in hash references. + + Link defs are in the form: ^[id]: url "optional title" + + + + Hashify HTML blocks + + + + + These are all the transformations that form block-level + tags like paragraphs, headers, and list items. + + + + + These are all the transformations that occur *within* block-level + tags like paragraphs, headers, and list items. + + + + + + + + Process the contents of a single ordered or unordered list, splitting it + into individual list items. + + + + + Encode/escape certain characters inside Markdown code runs. + + + The point is that in code, these characters are literals, and lose their + special Markdown meanings. + + + + + Smart processing for ampersands and angle brackets that need to be encoded. + + + + + Swap back in all the special characters we've hidden. + + + + + Remove one level of line-leading tabs or spaces + + + + + This is to emulate what's evailable in PHP + + + + + + + + Calculate an MD5 hash of an arbitrary string + + + + + + + when true, (most) bare plain URLs are auto-hyperlinked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, RETURN becomes a literal newline + WARNING: this is a significant deviation from the markdown spec + + + + + use ">" for HTML output, or " />" for XHTML output + + + + + when true, problematic URL characters like [, ], (, and so forth will be encoded + WARNING: this is a significant deviation from the markdown spec + + + + + when false, email addresses will never be auto-linked + WARNING: this is a significant deviation from the markdown spec + + + + + when true, bold and italic require non-word characters on either side + WARNING: this is a significant deviation from the markdown spec + + + + diff --git a/lib/msdeploy/TBEX.xml b/lib/msdeploy/TBEX.xml new file mode 100644 index 000000000..3c2fc97b2 --- /dev/null +++ b/lib/msdeploy/TBEX.xml @@ -0,0 +1,75 @@ + + + + + Getting Started with Orchard + Welcome to the Orchard community! We want your experience with your new site to be as smooth as possible. Please read this to get started... + http://orchardproject.net/docs/Getting-Started.ashx + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + Free Pluralsight Training on Orchard + Watch Pluralsight's free introduction to Orchard course. + http://www.pluralsight-training.net/microsoft/players/PSODPlayer.aspx?author=kevin-kuebler&name=introduction-to-orchard&mode=live&clip=0&course=orchard-fundamentals + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + More documentation + We have documentation available on a variety of topics. + http://orchardproject.net/docs/ + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + More videos + Learn through these great video tutorials. + http://orchardproject.net/docs/Orchard-TV.ashx + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + Orchard Gallery + Hundreds of free modules and themes are available from our gallery. + http://orchardproject.net/gallery + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + Orchard Forums + If you have questions, suggestions or just want to hang out with other Orchard users and experts, please visit our forums. + http://orchard.codeplex.com/discussions + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + + + + /admin + http://orchardproject.net/Themes/OrchardProject.Net/Images/orchardicon.png + + + + /Packaging/Gallery/Modules + http://orchardproject.net/Themes/OrchardProject.Net/Images/o.png + + + + /Packaging/Gallery/Themes + http://orchardproject.net/Themes/OrchardProject.Net/Images/o.png + + + + + modules + + + themes + + + media + + + web.config + + + * + + + diff --git a/src/Orchard.Azure/AzureFileSystem.cs b/src/Orchard.Azure/AzureFileSystem.cs index f1b594959..1697ba9d3 100644 --- a/src/Orchard.Azure/AzureFileSystem.cs +++ b/src/Orchard.Azure/AzureFileSystem.cs @@ -345,11 +345,15 @@ namespace Orchard.Azure { } public string GetPath() { - return _blob.Uri.ToString().Substring(_rootPath.Length).Trim('/'); + using (new HttpContextWeaver()) { + return _blob.Uri.ToString().Substring(_rootPath.Length).Trim('/'); + } } public long GetSize() { - return GetDirectorySize(_blob); + using (new HttpContextWeaver()) { + return GetDirectorySize(_blob); + } } public DateTime GetLastUpdated() { @@ -357,8 +361,10 @@ namespace Orchard.Azure { } public IStorageFolder GetParent() { - if ( _blob.Parent != null ) { - return new AzureBlobFolderStorage(_blob.Parent, _rootPath); + using (new HttpContextWeaver()) { + if (_blob.Parent != null) { + return new AzureBlobFolderStorage(_blob.Parent, _rootPath); + } } throw new ArgumentException("Directory " + _blob.Uri + " does not have a parent directory"); } diff --git a/src/Orchard.Azure/Logging/AzureAppender.cs b/src/Orchard.Azure/Logging/AzureAppender.cs new file mode 100644 index 000000000..e5fc5d261 --- /dev/null +++ b/src/Orchard.Azure/Logging/AzureAppender.cs @@ -0,0 +1,40 @@ +using System; +using Microsoft.WindowsAzure; +using Microsoft.WindowsAzure.Diagnostics.Management; +using Microsoft.WindowsAzure.ServiceRuntime; +using log4net.Appender; +using log4net.Core; + +namespace Orchard.Azure.Logging { + + /// + /// Azure specific implementation of a log4net appender. + /// Uses DataConnectionString to define the location of the log. + /// + public class AzureAppender : AppenderSkeleton { + private const string WadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"; + + public AzureAppender() { + + var cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(WadConnectionString)); + + var roleInstanceDiagnosticManager = cloudStorageAccount.CreateRoleInstanceDiagnosticManager( + RoleEnvironment.DeploymentId, + RoleEnvironment.CurrentRoleInstance.Role.Name, + RoleEnvironment.CurrentRoleInstance.Id); + + var diagnosticMonitorConfiguration = roleInstanceDiagnosticManager.GetCurrentConfiguration(); + diagnosticMonitorConfiguration.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1d); + diagnosticMonitorConfiguration.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1d); + + roleInstanceDiagnosticManager.SetCurrentConfiguration(diagnosticMonitorConfiguration); + } + + protected override void Append(LoggingEvent loggingEvent) { + var formattedLog = RenderLoggingEvent(loggingEvent); + + // this is the way to logging into Azure + System.Diagnostics.Trace.WriteLine(formattedLog); + } + } +} diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj b/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj index 4d2726fc6..84a86b69e 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj @@ -1,9 +1,10 @@  + Debug AnyCPU - 1.3.0 + 1.5.0 {03c5327d-4e8e-45a7-acd1-e18e7caa3c4a} Library Properties @@ -45,7 +46,8 @@ - $(MSBuildExtensionsPath)\Microsoft\Cloud Service\1.0\Visual Studio 10.0\ + 10.0 + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\1.5\ - + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg index 9600d5e76..d4c117dfc 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg @@ -4,6 +4,7 @@ + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef index 3503cc02c..e59d35ce6 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef @@ -8,6 +8,9 @@ + + + diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Config/log4net.config b/src/Orchard.Azure/Orchard.Azure.Web/Config/log4net.config index 7b1b9b36c..c41a6b0c8 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Config/log4net.config +++ b/src/Orchard.Azure/Orchard.Azure.Web/Config/log4net.config @@ -3,26 +3,25 @@ - + + - - - - - - - - - + + + + + + - + diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj index 6781b1839..3a862ed45 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj +++ b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj @@ -85,11 +85,7 @@ False - - False - ..\..\..\lib\sqlce\System.Data.SqlServerCe.dll - True - + False diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Web.config b/src/Orchard.Azure/Orchard.Azure.Web/Web.config index 7c86d8a39..23c55dc82 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Web.config +++ b/src/Orchard.Azure/Orchard.Azure.Web/Web.config @@ -36,6 +36,20 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Core/Title/Views/EditorTemplates/Parts.Title.TitlePart.cshtml b/src/Orchard.Web/Core/Title/Views/EditorTemplates/Parts.Title.TitlePart.cshtml new file mode 100644 index 000000000..db41838e7 --- /dev/null +++ b/src/Orchard.Web/Core/Title/Views/EditorTemplates/Parts.Title.TitlePart.cshtml @@ -0,0 +1,6 @@ +@model Orchard.Core.Title.Models.TitlePart + +
+ @Html.LabelFor(m => m.Title, T("Title")) + @Html.TextBoxFor(m => m.Title, new { @class = "large text" }) +
diff --git a/src/Orchard.Web/Core/Title/Views/Parts.Title.cshtml b/src/Orchard.Web/Core/Title/Views/Parts.Title.cshtml new file mode 100644 index 000000000..6024082e2 --- /dev/null +++ b/src/Orchard.Web/Core/Title/Views/Parts.Title.cshtml @@ -0,0 +1 @@ +

@Model.Title

\ No newline at end of file diff --git a/src/Orchard.Web/Core/Title/Views/Parts.Title_Summary.cshtml b/src/Orchard.Web/Core/Title/Views/Parts.Title_Summary.cshtml new file mode 100644 index 000000000..a1e1e7ed0 --- /dev/null +++ b/src/Orchard.Web/Core/Title/Views/Parts.Title_Summary.cshtml @@ -0,0 +1,6 @@ +@{ + Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem; + string title = Model.Title.ToString(); +} + +

@Html.ItemDisplayLink(title, contentItem)

\ No newline at end of file diff --git a/src/Orchard.Web/Core/Title/Views/Parts.Title_SummaryAdmin.cshtml b/src/Orchard.Web/Core/Title/Views/Parts.Title_SummaryAdmin.cshtml new file mode 100644 index 000000000..552cf4c0c --- /dev/null +++ b/src/Orchard.Web/Core/Title/Views/Parts.Title_SummaryAdmin.cshtml @@ -0,0 +1,6 @@ +@{ + Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem; + string title = Model.Title.ToString(); +} + +

@Html.ItemEditLink(title, contentItem)

\ No newline at end of file diff --git a/src/Orchard.Web/Core/Title/Views/Web.config b/src/Orchard.Web/Core/Title/Views/Web.config new file mode 100644 index 000000000..b7d215131 --- /dev/null +++ b/src/Orchard.Web/Core/Title/Views/Web.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Core/XmlRpc/Module.txt b/src/Orchard.Web/Core/XmlRpc/Module.txt index 2e9596360..c220905fc 100644 --- a/src/Orchard.Web/Core/XmlRpc/Module.txt +++ b/src/Orchard.Web/Core/XmlRpc/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The XmlRpc module enables creation of contents from client applications such as LiveWriter. FeatureDescription: XML-RPC opt-in implementation. Category: Content Publishing diff --git a/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs b/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs index 9cf9c395e..7228539db 100644 --- a/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs +++ b/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs @@ -59,7 +59,7 @@ namespace Lucene.Models { } public IDocumentIndex Add(string name, bool value) { - return Add(name, value.ToString()); + return Add(name, value ? 1 : 0); } public IDocumentIndex Add(string name, double value) { diff --git a/src/Orchard.Web/Modules/Lucene/Models/LuceneSearchHit.cs b/src/Orchard.Web/Modules/Lucene/Models/LuceneSearchHit.cs index 05b86b4c3..c2a57d84f 100644 --- a/src/Orchard.Web/Modules/Lucene/Models/LuceneSearchHit.cs +++ b/src/Orchard.Web/Modules/Lucene/Models/LuceneSearchHit.cs @@ -29,8 +29,7 @@ namespace Lucene.Models { } public bool GetBoolean(string name) { - var field = _doc.GetField(name); - return field == null ? false : bool.Parse(field.StringValue()); + return GetInt(name) > 0 ? true : false; } public string GetString(string name) { diff --git a/src/Orchard.Web/Modules/Lucene/Module.txt b/src/Orchard.Web/Modules/Lucene/Module.txt index ab7957fa6..03cd5dec6 100644 --- a/src/Orchard.Web/Modules/Lucene/Module.txt +++ b/src/Orchard.Web/Modules/Lucene/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Lucene module enables the site to be indexed using Lucene.NET. The index generated by this module can then be used by the search module to provide an integrated full-text search experience to a web site. FeatureDescription: Lucene indexing services. Category: Search diff --git a/src/Orchard.Web/Modules/Lucene/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Lucene/Properties/AssemblyInfo.cs index 21006ab4a..a02b3e4c6 100644 --- a/src/Orchard.Web/Modules/Lucene/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Lucene/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Lucene")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Lucene")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs index 22f08bdee..d67d4f111 100644 --- a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs +++ b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Lucene.Models; using Lucene.Net.Index; @@ -89,22 +88,20 @@ namespace Lucene.Services { return this; } - public ISearchBuilder WithField(string field, float value) { + public ISearchBuilder WithField(string field, double value) { CreatePendingClause(); - _query = NumericRangeQuery.NewFloatRange(field, value, value, true, true); + _query = NumericRangeQuery.NewDoubleRange(field, value, value, true, true); return this; } - public ISearchBuilder WithinRange(string field, float min, float max) { + public ISearchBuilder WithinRange(string field, double min, double max) { CreatePendingClause(); - _query = NumericRangeQuery.NewFloatRange(field, min, max, true, true); + _query = NumericRangeQuery.NewDoubleRange(field, min, max, true, true); return this; } public ISearchBuilder WithField(string field, bool value) { - CreatePendingClause(); - _query = new TermQuery(new Term(field, value.ToString().ToLower())); - return this; + return WithField(field, value ? 1 : 0); } public ISearchBuilder WithField(string field, DateTime value) { @@ -203,15 +200,19 @@ namespace Lucene.Services { return this; } + public ISearchBuilder SortByBoolean(string name) { + return SortByInteger(name); + } + public ISearchBuilder SortByString(string name) { _sort = name; _comparer = SortField.STRING; return this; } - public ISearchBuilder SortByFloat(string name) { + public ISearchBuilder SortByDouble(string name) { _sort = name; - _comparer = SortField.FLOAT; + _comparer = SortField.DOUBLE; return this; } diff --git a/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/grippie.png b/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/grippie.png new file mode 100644 index 000000000..6524d4167 Binary files /dev/null and b/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/grippie.png differ diff --git a/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/wmd-buttons.png b/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/wmd-buttons.png new file mode 100644 index 000000000..36ac79a28 Binary files /dev/null and b/src/Orchard.Web/Modules/Markdown/Content/Admin/Images/wmd-buttons.png differ diff --git a/src/Orchard.Web/Modules/Markdown/Content/Web.config b/src/Orchard.Web/Modules/Markdown/Content/Web.config new file mode 100644 index 000000000..df1c33504 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Content/Web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Markdown/Markdown.csproj b/src/Orchard.Web/Modules/Markdown/Markdown.csproj new file mode 100644 index 000000000..f9cccb15b --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Markdown.csproj @@ -0,0 +1,139 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {3158C928-888C-4A84-8BC1-4A8257489538} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Markdown + Markdown + v4.0 + false + + + 3.5 + + + false + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + ..\..\..\OrchardBasicCorrectness.ruleset + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + + + + ..\..\..\..\lib\markdown\MarkdownSharp.dll + True + + + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + Designer + + + + + Designer + + + + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 53593 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Markdown/Module.txt b/src/Orchard.Web/Modules/Markdown/Module.txt new file mode 100644 index 000000000..819cee8c9 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Module.txt @@ -0,0 +1,10 @@ +Name: Markdown +AntiForgery: enabled +Author: The Orchard Team +Website: http://orchardproject.net +Version: 1.3.0 +OrchardVersion: 1.3.0 +Description: The Markdown module enables rich text contents to be created using the Markdown syntax. +FeatureDescription: Markdown editor. +Category: Input Editor +Dependencies: Common \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Markdown/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Markdown/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..202fbeead --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; + +[assembly: AssemblyTitle("Markdown")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 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("146F4A3C-C611-4B60-A046-AC5C48D25C70")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] +[assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Markdown/ResourceManifest.cs b/src/Orchard.Web/Modules/Markdown/ResourceManifest.cs new file mode 100644 index 000000000..b330b255e --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/ResourceManifest.cs @@ -0,0 +1,16 @@ +using Orchard.UI.Resources; + +namespace Markdown { + public class ResourceManifest : IResourceManifestProvider { + public void BuildManifests(ResourceManifestBuilder builder) { + var manifest = builder.Add(); + manifest.DefineScript("Markdown_Converter").SetUrl("Markdown.Converter.js"); + manifest.DefineScript("Markdown_Sanitizer").SetUrl("Markdown.Sanitizer.js").SetDependencies("Markdown_Converter"); + manifest.DefineScript("Markdown_Editor").SetUrl("Markdown.Editor.js").SetDependencies("Markdown_Sanitizer"); + manifest.DefineScript("Resizer").SetUrl("jquery.textarearesizer.min.js"); + + manifest.DefineScript("OrchardMarkdown").SetUrl("orchard-markdown.js").SetDependencies("Resizer", "Markdown_Editor"); + manifest.DefineStyle("OrchardMarkdown").SetUrl("admin-markdown.css"); + } + } +} diff --git a/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Converter.js b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Converter.js new file mode 100644 index 000000000..da7025ad9 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Converter.js @@ -0,0 +1,1325 @@ +var Markdown; + +if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module + Markdown = exports; +else + Markdown = {}; + +// The following text is included for historical reasons, but should +// be taken with a pinch of salt; it's not all true anymore. + +// +// Wherever possible, Showdown is a straight, line-by-line port +// of the Perl version of Markdown. +// +// This is not a normal parser design; it's basically just a +// series of string substitutions. It's hard to read and +// maintain this way, but keeping Showdown close to the original +// design makes it easier to port new features. +// +// More importantly, Showdown behaves like markdown.pl in most +// edge cases. So web applications can do client-side preview +// in Javascript, and then build identical HTML on the server. +// +// This port needs the new RegExp functionality of ECMA 262, +// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers +// should do fine. Even with the new regular expression features, +// We do a lot of work to emulate Perl's regex functionality. +// The tricky changes in this file mostly have the "attacklab:" +// label. Major or self-explanatory changes don't. +// +// Smart diff tools like Araxis Merge will be able to match up +// this file with markdown.pl in a useful way. A little tweaking +// helps: in a copy of markdown.pl, replace "#" with "//" and +// replace "$text" with "text". Be sure to ignore whitespace +// and line endings. +// + + +// +// Usage: +// +// var text = "Markdown *rocks*."; +// +// var converter = new Markdown.Converter(); +// var html = converter.makeHtml(text); +// +// alert(html); +// +// Note: move the sample code to the bottom of this +// file before uncommenting it. +// + +(function () { + + function identity(x) { return x; } + function returnFalse(x) { return false; } + + function HookCollection() { } + + HookCollection.prototype = { + + chain: function (hookname, func) { + var original = this[hookname]; + if (!original) + throw new Error("unknown hook " + hookname); + + if (original === identity) + this[hookname] = func; + else + this[hookname] = function (x) { return func(original(x)); } + }, + set: function (hookname, func) { + if (!this[hookname]) + throw new Error("unknown hook " + hookname); + this[hookname] = func; + }, + addNoop: function (hookname) { + this[hookname] = identity; + }, + addFalse: function (hookname) { + this[hookname] = returnFalse; + } + }; + + Markdown.HookCollection = HookCollection; + + // g_urls and g_titles allow arbitrary user-entered strings as keys. This + // caused an exception (and hence stopped the rendering) when the user entered + // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this + // (since no builtin property starts with "s_"). See + // http://meta.stackoverflow.com/questions/64655/strange-wmd-bug + // (granted, switching from Array() to Object() alone would have left only __proto__ + // to be a problem) + function SaveHash() { } + SaveHash.prototype = { + set: function (key, value) { + this["s_" + key] = value; + }, + get: function (key) { + return this["s_" + key]; + } + }; + + Markdown.Converter = function () { + var pluginHooks = this.hooks = new HookCollection(); + pluginHooks.addNoop("plainLinkText"); // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link + pluginHooks.addNoop("preConversion"); // called with the orignal text as given to makeHtml. The result of this plugin hook is the actual markdown source that will be cooked + pluginHooks.addNoop("postConversion"); // called with the final cooked HTML code. The result of this plugin hook is the actual output of makeHtml + + // + // Private state of the converter instance: + // + + // Global hashes, used by various utility routines + var g_urls; + var g_titles; + var g_html_blocks; + + // Used to track when we're inside an ordered or unordered list + // (see _ProcessListItems() for details): + var g_list_level; + + this.makeHtml = function (text) { + + // + // Main function. The order in which other subs are called here is + // essential. Link and image substitutions need to happen before + // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the + // and tags get encoded. + // + + // This will only happen if makeHtml on the same converter instance is called from a plugin hook. + // Don't do that. + if (g_urls) + throw new Error("Recursive call to converter.makeHtml"); + + // Create the private state objects. + g_urls = new SaveHash(); + g_titles = new SaveHash(); + g_html_blocks = []; + g_list_level = 0; + + text = pluginHooks.preConversion(text); + + // attacklab: Replace ~ with ~T + // This lets us use tilde as an escape char to avoid md5 hashes + // The choice of character is arbitray; anything that isn't + // magic in Markdown will work. + text = text.replace(/~/g, "~T"); + + // attacklab: Replace $ with ~D + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g, "~D"); + + // Standardize line endings + text = text.replace(/\r\n/g, "\n"); // DOS to Unix + text = text.replace(/\r/g, "\n"); // Mac to Unix + + // Make sure text begins and ends with a couple of newlines: + text = "\n\n" + text + "\n\n"; + + // Convert all tabs to spaces. + text = _Detab(text); + + // Strip any lines consisting only of spaces and tabs. + // This makes subsequent regexen easier to write, because we can + // match consecutive blank lines with /\n+/ instead of something + // contorted like /[ \t]*\n+/ . + text = text.replace(/^[ \t]+$/mg, ""); + + // Turn block-level HTML blocks into hash entries + text = _HashHTMLBlocks(text); + + // Strip link definitions, store in hashes. + text = _StripLinkDefinitions(text); + + text = _RunBlockGamut(text); + + text = _UnescapeSpecialChars(text); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g, "$$"); + + // attacklab: Restore tildes + text = text.replace(/~T/g, "~"); + + text = pluginHooks.postConversion(text); + + g_html_blocks = g_titles = g_urls = null; + + return text; + }; + + function _StripLinkDefinitions(text) { + // + // Strips link definitions from text, stores the URLs and titles in + // hash references. + // + + // Link defs are in the form: ^[id]: url "optional title" + + /* + text = text.replace(/ + ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 + [ \t]* + \n? // maybe *one* newline + [ \t]* + ? // url = $2 + (?=\s|$) // lookahead for whitespace instead of the lookbehind removed below + [ \t]* + \n? // maybe one newline + [ \t]* + ( // (potential) title = $3 + (\n*) // any lines skipped = $4 attacklab: lookbehind removed + [ \t]+ + ["(] + (.+?) // title = $5 + [")] + [ \t]* + )? // title is optional + (?:\n+|$) + /gm, function(){...}); + */ + + text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm, + function (wholeMatch, m1, m2, m3, m4, m5) { + m1 = m1.toLowerCase(); + g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive + if (m4) { + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return m3; + } else if (m5) { + g_titles.set(m1, m5.replace(/"/g, """)); + } + + // Completely remove the definition from the text + return ""; + } + ); + + return text; + } + + function _HashHTMLBlocks(text) { + + // Hashify HTML blocks: + // We only want to do this for block-level HTML tags, such as headers, + // lists, and tables. That's because we still want to wrap

s around + // "paragraphs" that are wrapped in non-block-level tags, such as anchors, + // phrase emphasis, and spans. The list of tags we're looking for is + // hard-coded: + var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" + var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" + + // First, look for nested blocks, e.g.: + //

+ //
+ // tags for inner block must be indented. + //
+ //
+ // + // The outermost tags must start at the left margin for this to match, and + // the inner nested divs must be indented. + // We need to do this before the next, more liberal match, because the next + // match will start at the first `
` and stop at the first `
`. + + // attacklab: This regex can be expensive when it fails. + + /* + text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_a) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*?\n // any number of lines, minimally matching + // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement); + + // + // Now match more liberally, simply from `\n` to `\n` + // + + /* + text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_b) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*? // any number of lines, minimally matching + .* // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement); + + // Special case just for
. It was easier to make a special case than + // to make the other regex more complicated. + + /* + text = text.replace(/ + \n // Starting after a blank line + [ ]{0,3} + ( // save in $1 + (<(hr) // start tag = $2 + \b // word break + ([^<>])*? + \/?>) // the matching end tag + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement); + + // Special case for standalone HTML comments: + + /* + text = text.replace(/ + \n\n // Starting after a blank line + [ ]{0,3} // attacklab: g_tab_width - 1 + ( // save in $1 + -]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256 + > + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/\n\n[ ]{0,3}(-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement); + + // PHP and ASP-style processor instructions ( and <%...%>) + + /* + text = text.replace(/ + (?: + \n\n // Starting after a blank line + ) + ( // save in $1 + [ ]{0,3} // attacklab: g_tab_width - 1 + (?: + <([?%]) // $2 + [^\r]*? + \2> + ) + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement); + + return text; + } + + function hashElement(wholeMatch, m1) { + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/^\n+/, ""); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g, ""); + + // Replace the element text with a marker ("~KxK" where x is its key) + blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n"; + + return blockText; + } + + function _RunBlockGamut(text, doNotUnhash) { + // + // These are all the transformations that form block-level + // tags like paragraphs, headers, and list items. + // + text = _DoHeaders(text); + + // Do Horizontal Rules: + var replacement = "
\n"; + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement); + text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement); + text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement); + + text = _DoLists(text); + text = _DoCodeBlocks(text); + text = _DoBlockQuotes(text); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + //

tags around block-level tags. + text = _HashHTMLBlocks(text); + text = _FormParagraphs(text, doNotUnhash); + + return text; + } + + function _RunSpanGamut(text) { + // + // These are all the transformations that occur *within* block-level + // tags like paragraphs, headers, and list items. + // + + text = _DoCodeSpans(text); + text = _EscapeSpecialCharsWithinTagAttributes(text); + text = _EncodeBackslashEscapes(text); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = _DoImages(text); + text = _DoAnchors(text); + + // Make links out of things like `` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](). + text = _DoAutoLinks(text); + + text = text.replace(/~P/g, "://"); // put in place to prevent autolinking; reset now + + text = _EncodeAmpsAndAngles(text); + text = _DoItalicsAndBold(text); + + // Do hard breaks: + text = text.replace(/ +\n/g, "
\n"); + + return text; + } + + function _EscapeSpecialCharsWithinTagAttributes(text) { + // + // Within tags -- meaning between < and > -- encode [\ ` * _] so they + // don't conflict with their use in Markdown for code, italics and strong. + // + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + + // SE: changed the comment part of the regex + + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi; + + text = text.replace(regex, function (wholeMatch) { + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`"); + tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987 + return tag; + }); + + return text; + } + + function _DoAnchors(text) { + // + // Turn Markdown link shortcuts into XHTML
tags. + // + // + // First, handle reference-style links: [link text] [id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[] // or anything else + )* + ) + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + ) + ()()()() // pad remaining backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag); + + // + // Next, inline-style links: [link text](url "optional title") + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[\]] // or anything else + )* + ) + \] + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // Title = $7 + \6 // matching quote + [ \t]* // ignore any spaces/tabs between closing quote and ) + )? // title is optional + \) + ) + /g, writeAnchorTag); + */ + + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag); + + // + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ([^\[\]]+) // link text = $2; can't contain '[' or ']' + \] + ) + ()()()()() // pad rest of backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag); + + return text; + } + + function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) { + if (m7 == undefined) m7 = ""; + var whole_match = m1; + var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = link_text.toLowerCase().replace(/ ?\n/g, " "); + } + url = "#" + link_id; + + if (g_urls.get(link_id) != undefined) { + url = g_urls.get(link_id); + if (g_titles.get(link_id) != undefined) { + title = g_titles.get(link_id); + } + } + else { + if (whole_match.search(/\(\s*\)$/m) > -1) { + // Special case for explicit empty url + url = ""; + } else { + return whole_match; + } + } + } + url = encodeProblemUrlChars(url); + url = escapeCharacters(url, "*_"); + var result = ""; + + return result; + } + + function _DoImages(text) { + // + // Turn Markdown image shortcuts into tags. + // + + // + // First, handle reference-style labeled images: ![alt text][id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + ) + ()()()() // pad rest of backreferences + /g, writeImageTag); + */ + text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag); + + // + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + \s? // One optional whitespace character + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + ? // src url = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // title = $7 + \6 // matching quote + [ \t]* + )? // title is optional + \) + ) + /g, writeImageTag); + */ + text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag); + + return text; + } + + function writeImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) { + var whole_match = m1; + var alt_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (!title) title = ""; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = alt_text.toLowerCase().replace(/ ?\n/g, " "); + } + url = "#" + link_id; + + if (g_urls.get(link_id) != undefined) { + url = g_urls.get(link_id); + if (g_titles.get(link_id) != undefined) { + title = g_titles.get(link_id); + } + } + else { + return whole_match; + } + } + + alt_text = alt_text.replace(/"/g, """); + url = escapeCharacters(url, "*_"); + var result = "\""" + _RunSpanGamut(m1) + "\n\n"; } + ); + + text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, + function (matchFound, m1) { return "

" + _RunSpanGamut(m1) + "

\n\n"; } + ); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + + /* + text = text.replace(/ + ^(\#{1,6}) // $1 = string of #'s + [ \t]* + (.+?) // $2 = Header text + [ \t]* + \#* // optional closing #'s (not counted) + \n+ + /gm, function() {...}); + */ + + text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, + function (wholeMatch, m1, m2) { + var h_level = m1.length; + return "" + _RunSpanGamut(m2) + "\n\n"; + } + ); + + return text; + } + + function _DoLists(text) { + // + // Form HTML ordered (numbered) and unordered (bulleted) lists. + // + + // attacklab: add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += "~0"; + + // Re-usable pattern to match any entirel ul or ol list: + + /* + var whole_list = / + ( // $1 = whole list + ( // $2 + [ ]{0,3} // attacklab: g_tab_width - 1 + ([*+-]|\d+[.]) // $3 = first list item marker + [ \t]+ + ) + [^\r]+? + ( // $4 + ~0 // sentinel for workaround; should be $ + | + \n{2,} + (?=\S) + (?! // Negative lookahead for another list item marker + [ \t]* + (?:[*+-]|\d+[.])[ \t]+ + ) + ) + ) + /g + */ + var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + if (g_list_level) { + text = text.replace(whole_list, function (wholeMatch, m1, m2) { + var list = m1; + var list_type = (m2.search(/[*+-]/g) > -1) ? "ul" : "ol"; + + var result = _ProcessListItems(list, list_type); + + // Trim any trailing whitespace, to put the closing `` + // up on the preceding line, to get it past the current stupid + // HTML block parser. This is a hack to work around the terrible + // hack that is the HTML block parser. + result = result.replace(/\s+$/, ""); + result = "<" + list_type + ">" + result + "\n"; + return result; + }); + } else { + whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; + text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) { + var runup = m1; + var list = m2; + + var list_type = (m3.search(/[*+-]/g) > -1) ? "ul" : "ol"; + var result = _ProcessListItems(list, list_type); + result = runup + "<" + list_type + ">\n" + result + "\n"; + return result; + }); + } + + // attacklab: strip sentinel + text = text.replace(/~0/, ""); + + return text; + } + + var _listItemMarkers = { ol: "\\d+[.]", ul: "[*+-]" }; + + function _ProcessListItems(list_str, list_type) { + // + // Process the contents of a single ordered or unordered list, splitting it + // into individual list items. + // + // list_type is either "ul" or "ol". + + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + + g_list_level++; + + // trim trailing blank lines: + list_str = list_str.replace(/\n{2,}$/, "\n"); + + // attacklab: add sentinel to emulate \z + list_str += "~0"; + + // In the original attacklab showdown, list_type was not given to this function, and anything + // that matched /[*+-]|\d+[.]/ would just create the next
  • , causing this mismatch: + // + // Markdown rendered by WMD rendered by MarkdownSharp + // ------------------------------------------------------------------ + // 1. first 1. first 1. first + // 2. second 2. second 2. second + // - third 3. third * third + // + // We changed this to behave identical to MarkdownSharp. This is the constructed RegEx, + // with {MARKER} being one of \d+[.] or [*+-], depending on list_type: + + /* + list_str = list_str.replace(/ + (^[ \t]*) // leading whitespace = $1 + ({MARKER}) [ \t]+ // list marker = $2 + ([^\r]+? // list item text = $3 + (\n+) + ) + (?= + (~0 | \2 ({MARKER}) [ \t]+) + ) + /gm, function(){...}); + */ + + var marker = _listItemMarkers[list_type]; + var re = new RegExp("(^[ \\t]*)(" + marker + ")[ \\t]+([^\\r]+?(\\n+))(?=(~0|\\1(" + marker + ")[ \\t]+))", "gm"); + var last_item_had_a_double_newline = false; + list_str = list_str.replace(re, + function (wholeMatch, m1, m2, m3) { + var item = m3; + var leading_space = m1; + var ends_with_double_newline = /\n\n$/.test(item); + var contains_double_newline = ends_with_double_newline || item.search(/\n{2,}/) > -1; + + if (contains_double_newline || last_item_had_a_double_newline) { + item = _RunBlockGamut(_Outdent(item), /* doNotUnhash = */true); + } + else { + // Recursion for sub-lists: + item = _DoLists(_Outdent(item)); + item = item.replace(/\n$/, ""); // chomp(item) + item = _RunSpanGamut(item); + } + last_item_had_a_double_newline = ends_with_double_newline; + return "
  • " + item + "
  • \n"; + } + ); + + // attacklab: strip sentinel + list_str = list_str.replace(/~0/g, ""); + + g_list_level--; + return list_str; + } + + function _DoCodeBlocks(text) { + // + // Process Markdown `
    ` blocks.
    +            //  
    +
    +            /*
    +            text = text.replace(/
    +                (?:\n\n|^)
    +                (                               // $1 = the code block -- one or more lines, starting with a space/tab
    +                    (?:
    +                        (?:[ ]{4}|\t)           // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
    +                        .*\n+
    +                    )+
    +                )
    +                (\n*[ ]{0,3}[^ \t\n]|(?=~0))    // attacklab: g_tab_width
    +            /g ,function(){...});
    +            */
    +
    +            // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
    +            text += "~0";
    +
    +            text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
    +                function (wholeMatch, m1, m2) {
    +                    var codeblock = m1;
    +                    var nextChar = m2;
    +
    +                    codeblock = _EncodeCode(_Outdent(codeblock));
    +                    codeblock = _Detab(codeblock);
    +                    codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
    +                    codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
    +
    +                    codeblock = "
    " + codeblock + "\n
    "; + + return "\n\n" + codeblock + "\n\n" + nextChar; + } + ); + + // attacklab: strip sentinel + text = text.replace(/~0/, ""); + + return text; + } + + function hashBlock(text) { + text = text.replace(/(^\n+|\n+$)/g, ""); + return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n"; + } + + function _DoCodeSpans(text) { + // + // * Backtick quotes are used for spans. + // + // * You can use multiple backticks as the delimiters if you want to + // include literal backticks in the code span. So, this input: + // + // Just type ``foo `bar` baz`` at the prompt. + // + // Will translate to: + // + //

    Just type foo `bar` baz at the prompt.

    + // + // There's no arbitrary limit to the number of backticks you + // can use as delimters. If you need three consecutive backticks + // in your code, use four for delimiters, etc. + // + // * You can use spaces to get literal backticks at the edges: + // + // ... type `` `bar` `` ... + // + // Turns to: + // + // ... type `bar` ... + // + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function (wholeMatch, m1, m2, m3, m4) { + var c = m3; + c = c.replace(/^([ \t]*)/g, ""); // leading whitespace + c = c.replace(/[ \t]*$/g, ""); // trailing whitespace + c = _EncodeCode(c); + return m1 + "" + c + ""; + } + ); + + return text; + } + + function _EncodeCode(text) { + // + // Encode/escape certain characters inside Markdown code runs. + // The point is that in code, these characters are literals, + // and lose their special Markdown meanings. + // + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g, "&"); + + // Do the angle bracket song and dance: + text = text.replace(//g, ">"); + + // Now, escape characters that are magic in Markdown: + text = escapeCharacters(text, "\*_{}[]\\", false); + + // jj the line above breaks this: + //--- + + //* Item + + // 1. Subitem + + // special char: * + //--- + + return text; + } + + function _DoItalicsAndBold(text) { + + // must go first: + text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g, + "$1$3$4"); + + text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g, + "$1$3$4"); + + return text; + } + + function _DoBlockQuotes(text) { + + /* + text = text.replace(/ + ( // Wrap whole match in $1 + ( + ^[ \t]*>[ \t]? // '>' at the start of a line + .+\n // rest of the first line + (.+\n)* // subsequent consecutive lines + \n* // blanks + )+ + ) + /gm, function(){...}); + */ + + text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, + function (wholeMatch, m1) { + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/~0/g, ""); + + bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines + bq = _RunBlockGamut(bq); // recurse + + bq = bq.replace(/(^|\n)/g, "$1 "); + // These leading spaces screw with
     content, so we need to fix that:
    +                    bq = bq.replace(
    +                            /(\s*
    [^\r]+?<\/pre>)/gm,
    +                        function (wholeMatch, m1) {
    +                            var pre = m1;
    +                            // attacklab: hack around Konqueror 3.5.4 bug:
    +                            pre = pre.replace(/^  /mg, "~0");
    +                            pre = pre.replace(/~0/g, "");
    +                            return pre;
    +                        });
    +
    +                    return hashBlock("
    \n" + bq + "\n
    "); + } + ); + return text; + } + + function _FormParagraphs(text, doNotUnhash) { + // + // Params: + // $text - string to process with html

    tags + // + + // Strip leading and trailing lines: + text = text.replace(/^\n+/g, ""); + text = text.replace(/\n+$/g, ""); + + var grafs = text.split(/\n{2,}/g); + var grafsOut = []; + + var markerRe = /~K(\d+)K/; + + // + // Wrap

    tags. + // + var end = grafs.length; + for (var i = 0; i < end; i++) { + var str = grafs[i]; + + // if this is an HTML marker, copy it + if (markerRe.test(str)) { + grafsOut.push(str); + } + else if (/\S/.test(str)) { + str = _RunSpanGamut(str); + str = str.replace(/^([ \t]*)/g, "

    "); + str += "

    " + grafsOut.push(str); + } + + } + // + // Unhashify HTML blocks + // + if (!doNotUnhash) { + end = grafsOut.length; + for (var i = 0; i < end; i++) { + var foundAny = true; + while (foundAny) { // we may need several runs, since the data may be nested + foundAny = false; + grafsOut[i] = grafsOut[i].replace(/~K(\d+)K/g, function (wholeMatch, id) { + foundAny = true; + return g_html_blocks[id]; + }); + } + } + } + return grafsOut.join("\n\n"); + } + + function _EncodeAmpsAndAngles(text) { + // Smart processing for ampersands and angle brackets that need to be encoded. + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&"); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?\$!])/gi, "<"); + + return text; + } + + function _EncodeBackslashEscapes(text) { + // + // Parameter: String. + // Returns: The string, with after processing the following backslash + // escape sequences. + // + + // attacklab: The polite way to do this is with the new + // escapeCharacters() function: + // + // text = escapeCharacters(text,"\\",true); + // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + // + // ...but we're sidestepping its use of the (slow) RegExp constructor + // as an optimization for Firefox. This function gets called a LOT. + + text = text.replace(/\\(\\)/g, escapeCharacters_callback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, escapeCharacters_callback); + return text; + } + + function _DoAutoLinks(text) { + + // note that at this point, all other URL in the text are already hyperlinked as
    + // *except* for the case + + // automatically add < and > around unadorned raw hyperlinks + // must be preceded by space/BOF and followed by non-word/EOF character + text = text.replace(/(^|\s)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)/gi, "$1<$2$3>$4"); + + // autolink anything like + + var replacer = function (wholematch, m1) { return "" + pluginHooks.plainLinkText(m1) + ""; } + text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer); + + // Email addresses: + /* + text = text.replace(/ + < + (?:mailto:)? + ( + [-.\w]+ + \@ + [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ + ) + > + /gi, _DoAutoLinks_callback()); + */ + + /* disabling email autolinking, since we don't do that on the server, either + text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, + function(wholeMatch,m1) { + return _EncodeEmailAddress( _UnescapeSpecialChars(m1) ); + } + ); + */ + return text; + } + + function _UnescapeSpecialChars(text) { + // + // Swap back in all the special characters we've hidden. + // + text = text.replace(/~E(\d+)E/g, + function (wholeMatch, m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + } + ); + return text; + } + + function _Outdent(text) { + // + // Remove one level of line-leading tabs or spaces + // + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + text = text.replace(/^(\t|[ ]{1,4})/gm, "~0"); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/~0/g, "") + + return text; + } + + function _Detab(text) { + if (!/\t/.test(text)) + return text; + + var spaces = [" ", " ", " ", " "], + skew = 0, + v; + + return text.replace(/[\n\t]/g, function (match, offset) { + if (match === "\n") { + skew = offset + 1; + return match; + } + v = (offset - skew) % 4; + skew = offset + 1; + return spaces[v]; + }); + } + + // + // attacklab: Utility functions + // + + var _problemUrlChars = /(?:["'*()[\]:]|~D)/g; + + // hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems + function encodeProblemUrlChars(url) { + if (!url) + return ""; + + var len = url.length; + + return url.replace(_problemUrlChars, function (match, offset) { + if (match == "~D") // escape for dollar + return "%24"; + if (match == ":") { + if (offset == len - 1 || /[0-9\/]/.test(url.charAt(offset + 1))) + return ":" + } + return "%" + match.charCodeAt(0).toString(16); + }); + } + + + function escapeCharacters(text, charsToEscape, afterBackslash) { + // First we have to escape the escape characters so that + // we can build a character class out of them + var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])"; + + if (afterBackslash) { + regexString = "\\\\" + regexString; + } + + var regex = new RegExp(regexString, "g"); + text = text.replace(regex, escapeCharacters_callback); + + return text; + } + + + function escapeCharacters_callback(wholeMatch, m1) { + var charCodeToEscape = m1.charCodeAt(0); + return "~E" + charCodeToEscape + "E"; + } + + }; // end of the Markdown.Converter constructor + +})(); diff --git a/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Editor.js b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Editor.js new file mode 100644 index 000000000..17f43112c --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Editor.js @@ -0,0 +1,2109 @@ +// needs Markdown.Converter.js at the moment + +(function () { + + var util = {}, + position = {}, + ui = {}, + doc = window.document, + re = window.RegExp, + nav = window.navigator, + SETTINGS = { lineLength: 72 }, + + // Used to work around some browser bugs where we can't use feature testing. + uaSniffed = { + isIE: /msie/.test(nav.userAgent.toLowerCase()), + isIE_5or6: /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase()), + isOpera: /opera/.test(nav.userAgent.toLowerCase()) + }; + + + // ------------------------------------------------------------------- + // YOUR CHANGES GO HERE + // + // I've tried to localize the things you are likely to change to + // this area. + // ------------------------------------------------------------------- + + // The text that appears on the upper part of the dialog box when + // entering links. + var linkDialogText = "

    Insert Hyperlink

    http://example.com/ \"optional title\"

    "; + var imageDialogText = "

    Insert Image

    http://example.com/images/diagram.jpg \"optional title\"

    Need free image hosting?

    "; + + // The default text that appears in the dialog input box when entering + // links. + var imageDefaultText = "http://"; + var linkDefaultText = "http://"; + + var defaultHelpHoverTitle = "Markdown Editing Help"; + + // ------------------------------------------------------------------- + // END OF YOUR CHANGES + // ------------------------------------------------------------------- + + // help, if given, should have a property "handler", the click handler for the help button, + // and can have an optional property "title" for the button's tooltip (defaults to "Markdown Editing Help"). + // If help isn't given, not help button is created. + // + // The constructed editor object has the methods: + // - getConverter() returns the markdown converter object that was passed to the constructor + // - run() actually starts the editor; should be called after all necessary plugins are registered. Calling this more than once is a no-op. + // - refreshPreview() forces the preview to be updated. This method is only available after run() was called. + Markdown.Editor = function (markdownConverter, idPostfix, help) { + + idPostfix = idPostfix || ""; + + var hooks = this.hooks = new Markdown.HookCollection(); + hooks.addNoop("onPreviewRefresh"); // called with no arguments after the preview has been refreshed + hooks.addNoop("postBlockquoteCreation"); // called with the user's selection *after* the blockquote was created; should return the actual to-be-inserted text + hooks.addFalse("insertImageDialog"); /* called with one parameter: a callback to be called with the URL of the image. If the application creates + * its own image insertion dialog, this hook should return true, and the callback should be called with the chosen + * image url (or null if the user cancelled). If this hook returns false, the default dialog will be used. + */ + + this.getConverter = function () { return markdownConverter; } + + var that = this, + panels; + + this.run = function () { + if (panels) + return; // already initialized + + panels = new PanelCollection(idPostfix); + var commandManager = new CommandManager(hooks); + var previewManager = new PreviewManager(markdownConverter, panels, function () { hooks.onPreviewRefresh(); }); + var undoManager, uiManager; + + if (!/\?noundo/.test(doc.location.href)) { + undoManager = new UndoManager(function () { + previewManager.refresh(); + if (uiManager) // not available on the first call + uiManager.setUndoRedoButtonStates(); + }, panels); + } + + uiManager = new UIManager(idPostfix, panels, undoManager, previewManager, commandManager, help); + uiManager.setUndoRedoButtonStates(); + + var forceRefresh = that.refreshPreview = function () { previewManager.refresh(true); }; + + forceRefresh(); + }; + + } + + // before: contains all the text in the input box BEFORE the selection. + // after: contains all the text in the input box AFTER the selection. + function Chunks() { } + + // startRegex: a regular expression to find the start tag + // endRegex: a regular expresssion to find the end tag + Chunks.prototype.findTags = function (startRegex, endRegex) { + + var chunkObj = this; + var regex; + + if (startRegex) { + + regex = util.extendRegExp(startRegex, "", "$"); + + this.before = this.before.replace(regex, + function (match) { + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + + regex = util.extendRegExp(startRegex, "^", ""); + + this.selection = this.selection.replace(regex, + function (match) { + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + } + + if (endRegex) { + + regex = util.extendRegExp(endRegex, "", "$"); + + this.selection = this.selection.replace(regex, + function (match) { + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + + regex = util.extendRegExp(endRegex, "^", ""); + + this.after = this.after.replace(regex, + function (match) { + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + } + }; + + // If remove is false, the whitespace is transferred + // to the before/after regions. + // + // If remove is true, the whitespace disappears. + Chunks.prototype.trimWhitespace = function (remove) { + var beforeReplacer, afterReplacer, that = this; + if (remove) { + beforeReplacer = afterReplacer = ""; + } else { + beforeReplacer = function (s) { that.before += s; return ""; } + afterReplacer = function (s) { that.after = s + that.after; return ""; } + } + + this.selection = this.selection.replace(/^(\s*)/, beforeReplacer).replace(/(\s*)$/, afterReplacer); + }; + + + Chunks.prototype.skipLines = function (nLinesBefore, nLinesAfter, findExtraNewlines) { + + if (nLinesBefore === undefined) { + nLinesBefore = 1; + } + + if (nLinesAfter === undefined) { + nLinesAfter = 1; + } + + nLinesBefore++; + nLinesAfter++; + + var regexText; + var replacementText; + + // chrome bug ... documented at: http://meta.stackoverflow.com/questions/63307/blockquote-glitch-in-editor-in-chrome-6-and-7/65985#65985 + if (navigator.userAgent.match(/Chrome/)) { + "X".match(/()./); + } + + this.selection = this.selection.replace(/(^\n*)/, ""); + + this.startTag = this.startTag + re.$1; + + this.selection = this.selection.replace(/(\n*$)/, ""); + this.endTag = this.endTag + re.$1; + this.startTag = this.startTag.replace(/(^\n*)/, ""); + this.before = this.before + re.$1; + this.endTag = this.endTag.replace(/(\n*$)/, ""); + this.after = this.after + re.$1; + + if (this.before) { + + regexText = replacementText = ""; + + while (nLinesBefore--) { + regexText += "\\n?"; + replacementText += "\n"; + } + + if (findExtraNewlines) { + regexText = "\\n*"; + } + this.before = this.before.replace(new re(regexText + "$", ""), replacementText); + } + + if (this.after) { + + regexText = replacementText = ""; + + while (nLinesAfter--) { + regexText += "\\n?"; + replacementText += "\n"; + } + if (findExtraNewlines) { + regexText = "\\n*"; + } + + this.after = this.after.replace(new re(regexText, ""), replacementText); + } + }; + + // end of Chunks + + // A collection of the important regions on the page. + // Cached so we don't have to keep traversing the DOM. + // Also holds ieCachedRange and ieCachedScrollTop, where necessary; working around + // this issue: + // Internet explorer has problems with CSS sprite buttons that use HTML + // lists. When you click on the background image "button", IE will + // select the non-existent link text and discard the selection in the + // textarea. The solution to this is to cache the textarea selection + // on the button's mousedown event and set a flag. In the part of the + // code where we need to grab the selection, we check for the flag + // and, if it's set, use the cached area instead of querying the + // textarea. + // + // This ONLY affects Internet Explorer (tested on versions 6, 7 + // and 8) and ONLY on button clicks. Keyboard shortcuts work + // normally since the focus never leaves the textarea. + function PanelCollection(postfix) { + this.buttonBar = doc.getElementById("wmd-button-bar" + postfix); + this.preview = doc.getElementById("wmd-preview" + postfix); + this.input = doc.getElementById("wmd-input" + postfix); + }; + + // Returns true if the DOM element is visible, false if it's hidden. + // Checks if display is anything other than none. + util.isVisible = function (elem) { + + if (window.getComputedStyle) { + // Most browsers + return window.getComputedStyle(elem, null).getPropertyValue("display") !== "none"; + } + else if (elem.currentStyle) { + // IE + return elem.currentStyle["display"] !== "none"; + } + }; + + + // Adds a listener callback to a DOM element which is fired on a specified + // event. + util.addEvent = function (elem, event, listener) { + if (elem.attachEvent) { + // IE only. The "on" is mandatory. + elem.attachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.addEventListener(event, listener, false); + } + }; + + + // Removes a listener callback from a DOM element which is fired on a specified + // event. + util.removeEvent = function (elem, event, listener) { + if (elem.detachEvent) { + // IE only. The "on" is mandatory. + elem.detachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.removeEventListener(event, listener, false); + } + }; + + // Converts \r\n and \r to \n. + util.fixEolChars = function (text) { + text = text.replace(/\r\n/g, "\n"); + text = text.replace(/\r/g, "\n"); + return text; + }; + + // Extends a regular expression. Returns a new RegExp + // using pre + regex + post as the expression. + // Used in a few functions where we have a base + // expression and we want to pre- or append some + // conditions to it (e.g. adding "$" to the end). + // The flags are unchanged. + // + // regex is a RegExp, pre and post are strings. + util.extendRegExp = function (regex, pre, post) { + + if (pre === null || pre === undefined) { + pre = ""; + } + if (post === null || post === undefined) { + post = ""; + } + + var pattern = regex.toString(); + var flags; + + // Replace the flags with empty space and store them. + pattern = pattern.replace(/\/([gim]*)$/, ""); + flags = re.$1; + + // Remove the slash delimiters on the regular expression. + pattern = pattern.replace(/(^\/|\/$)/g, ""); + pattern = pre + pattern + post; + + return new re(pattern, flags); + } + + // UNFINISHED + // The assignment in the while loop makes jslint cranky. + // I'll change it to a better loop later. + position.getTop = function (elem, isInner) { + var result = elem.offsetTop; + if (!isInner) { + while (elem = elem.offsetParent) { + result += elem.offsetTop; + } + } + return result; + }; + + position.getHeight = function (elem) { + return elem.offsetHeight || elem.scrollHeight; + }; + + position.getWidth = function (elem) { + return elem.offsetWidth || elem.scrollWidth; + }; + + position.getPageSize = function () { + + var scrollWidth, scrollHeight; + var innerWidth, innerHeight; + + // It's not very clear which blocks work with which browsers. + if (self.innerHeight && self.scrollMaxY) { + scrollWidth = doc.body.scrollWidth; + scrollHeight = self.innerHeight + self.scrollMaxY; + } + else if (doc.body.scrollHeight > doc.body.offsetHeight) { + scrollWidth = doc.body.scrollWidth; + scrollHeight = doc.body.scrollHeight; + } + else { + scrollWidth = doc.body.offsetWidth; + scrollHeight = doc.body.offsetHeight; + } + + if (self.innerHeight) { + // Non-IE browser + innerWidth = self.innerWidth; + innerHeight = self.innerHeight; + } + else if (doc.documentElement && doc.documentElement.clientHeight) { + // Some versions of IE (IE 6 w/ a DOCTYPE declaration) + innerWidth = doc.documentElement.clientWidth; + innerHeight = doc.documentElement.clientHeight; + } + else if (doc.body) { + // Other versions of IE + innerWidth = doc.body.clientWidth; + innerHeight = doc.body.clientHeight; + } + + var maxWidth = Math.max(scrollWidth, innerWidth); + var maxHeight = Math.max(scrollHeight, innerHeight); + return [maxWidth, maxHeight, innerWidth, innerHeight]; + }; + + // Handles pushing and popping TextareaStates for undo/redo commands. + // I should rename the stack variables to list. + function UndoManager(callback, panels) { + + var undoObj = this; + var undoStack = []; // A stack of undo states + var stackPtr = 0; // The index of the current state + var mode = "none"; + var lastState; // The last state + var timer; // The setTimeout handle for cancelling the timer + var inputStateObj; + + // Set the mode for later logic steps. + var setMode = function (newMode, noSave) { + if (mode != newMode) { + mode = newMode; + if (!noSave) { + saveState(); + } + } + + if (!uaSniffed.isIE || mode != "moving") { + timer = setTimeout(refreshState, 1); + } + else { + inputStateObj = null; + } + }; + + var refreshState = function (isInitialState) { + inputStateObj = new TextareaState(panels, isInitialState); + timer = undefined; + }; + + this.setCommandMode = function () { + mode = "command"; + saveState(); + timer = setTimeout(refreshState, 0); + }; + + this.canUndo = function () { + return stackPtr > 1; + }; + + this.canRedo = function () { + if (undoStack[stackPtr + 1]) { + return true; + } + return false; + }; + + // Removes the last state and restores it. + this.undo = function () { + + if (undoObj.canUndo()) { + if (lastState) { + // What about setting state -1 to null or checking for undefined? + lastState.restore(); + lastState = null; + } + else { + undoStack[stackPtr] = new TextareaState(panels); + undoStack[--stackPtr].restore(); + + if (callback) { + callback(); + } + } + } + + mode = "none"; + panels.input.focus(); + refreshState(); + }; + + // Redo an action. + this.redo = function () { + + if (undoObj.canRedo()) { + + undoStack[++stackPtr].restore(); + + if (callback) { + callback(); + } + } + + mode = "none"; + panels.input.focus(); + refreshState(); + }; + + // Push the input area state to the stack. + var saveState = function () { + var currState = inputStateObj || new TextareaState(panels); + + if (!currState) { + return false; + } + if (mode == "moving") { + if (!lastState) { + lastState = currState; + } + return; + } + if (lastState) { + if (undoStack[stackPtr - 1].text != lastState.text) { + undoStack[stackPtr++] = lastState; + } + lastState = null; + } + undoStack[stackPtr++] = currState; + undoStack[stackPtr + 1] = null; + if (callback) { + callback(); + } + }; + + var handleCtrlYZ = function (event) { + + var handled = false; + + if (event.ctrlKey || event.metaKey) { + + // IE and Opera do not support charCode. + var keyCode = event.charCode || event.keyCode; + var keyCodeChar = String.fromCharCode(keyCode); + + switch (keyCodeChar) { + + case "y": + undoObj.redo(); + handled = true; + break; + + case "z": + if (!event.shiftKey) { + undoObj.undo(); + } + else { + undoObj.redo(); + } + handled = true; + break; + } + } + + if (handled) { + if (event.preventDefault) { + event.preventDefault(); + } + if (window.event) { + window.event.returnValue = false; + } + return; + } + }; + + // Set the mode depending on what is going on in the input area. + var handleModeChange = function (event) { + + if (!event.ctrlKey && !event.metaKey) { + + var keyCode = event.keyCode; + + if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) { + // 33 - 40: page up/dn and arrow keys + // 63232 - 63235: page up/dn and arrow keys on safari + setMode("moving"); + } + else if (keyCode == 8 || keyCode == 46 || keyCode == 127) { + // 8: backspace + // 46: delete + // 127: delete + setMode("deleting"); + } + else if (keyCode == 13) { + // 13: Enter + setMode("newlines"); + } + else if (keyCode == 27) { + // 27: escape + setMode("escape"); + } + else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) { + // 16-20 are shift, etc. + // 91: left window key + // I think this might be a little messed up since there are + // a lot of nonprinting keys above 20. + setMode("typing"); + } + } + }; + + var setEventHandlers = function () { + util.addEvent(panels.input, "keypress", function (event) { + // keyCode 89: y + // keyCode 90: z + if ((event.ctrlKey || event.metaKey) && (event.keyCode == 89 || event.keyCode == 90)) { + event.preventDefault(); + } + }); + + var handlePaste = function () { + if (uaSniffed.isIE || (inputStateObj && inputStateObj.text != panels.input.value)) { + if (timer == undefined) { + mode = "paste"; + saveState(); + refreshState(); + } + } + }; + + util.addEvent(panels.input, "keydown", handleCtrlYZ); + util.addEvent(panels.input, "keydown", handleModeChange); + util.addEvent(panels.input, "mousedown", function () { + setMode("moving"); + }); + + panels.input.onpaste = handlePaste; + panels.input.ondrop = handlePaste; + }; + + var init = function () { + setEventHandlers(); + refreshState(true); + saveState(); + }; + + init(); + } + + // end of UndoManager + + // The input textarea state/contents. + // This is used to implement undo/redo by the undo manager. + function TextareaState(panels, isInitialState) { + + // Aliases + var stateObj = this; + var inputArea = panels.input; + this.init = function () { + if (!util.isVisible(inputArea)) { + return; + } + if (!isInitialState && doc.activeElement && doc.activeElement !== inputArea) { // this happens when tabbing out of the input box + return; + } + + this.setInputAreaSelectionStartEnd(); + this.scrollTop = inputArea.scrollTop; + if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) { + this.text = inputArea.value; + } + + } + + // Sets the selected text in the input box after we've performed an + // operation. + this.setInputAreaSelection = function () { + + if (!util.isVisible(inputArea)) { + return; + } + + if (inputArea.selectionStart !== undefined && !uaSniffed.isOpera) { + + inputArea.focus(); + inputArea.selectionStart = stateObj.start; + inputArea.selectionEnd = stateObj.end; + inputArea.scrollTop = stateObj.scrollTop; + } + else if (doc.selection) { + + if (doc.activeElement && doc.activeElement !== inputArea) { + return; + } + + inputArea.focus(); + var range = inputArea.createTextRange(); + range.moveStart("character", -inputArea.value.length); + range.moveEnd("character", -inputArea.value.length); + range.moveEnd("character", stateObj.end); + range.moveStart("character", stateObj.start); + range.select(); + } + }; + + this.setInputAreaSelectionStartEnd = function () { + + if (!panels.ieCachedRange && (inputArea.selectionStart || inputArea.selectionStart === 0)) { + + stateObj.start = inputArea.selectionStart; + stateObj.end = inputArea.selectionEnd; + } + else if (doc.selection) { + + stateObj.text = util.fixEolChars(inputArea.value); + + // IE loses the selection in the textarea when buttons are + // clicked. On IE we cache the selection. Here, if something is cached, + // we take it. + var range = panels.ieCachedRange || doc.selection.createRange(); + + var fixedRange = util.fixEolChars(range.text); + var marker = "\x07"; + var markedRange = marker + fixedRange + marker; + range.text = markedRange; + var inputText = util.fixEolChars(inputArea.value); + + range.moveStart("character", -markedRange.length); + range.text = fixedRange; + + stateObj.start = inputText.indexOf(marker); + stateObj.end = inputText.lastIndexOf(marker) - marker.length; + + var len = stateObj.text.length - util.fixEolChars(inputArea.value).length; + + if (len) { + range.moveStart("character", -fixedRange.length); + while (len--) { + fixedRange += "\n"; + stateObj.end += 1; + } + range.text = fixedRange; + } + + if (panels.ieCachedRange) + stateObj.scrollTop = panels.ieCachedScrollTop; // this is set alongside with ieCachedRange + + panels.ieCachedRange = null; + + this.setInputAreaSelection(); + } + }; + + // Restore this state into the input area. + this.restore = function () { + + if (stateObj.text != undefined && stateObj.text != inputArea.value) { + inputArea.value = stateObj.text; + } + this.setInputAreaSelection(); + inputArea.scrollTop = stateObj.scrollTop; + }; + + // Gets a collection of HTML chunks from the inptut textarea. + this.getChunks = function () { + + var chunk = new Chunks(); + chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start)); + chunk.startTag = ""; + chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end)); + chunk.endTag = ""; + chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end)); + chunk.scrollTop = stateObj.scrollTop; + + return chunk; + }; + + // Sets the TextareaState properties given a chunk of markdown. + this.setChunks = function (chunk) { + + chunk.before = chunk.before + chunk.startTag; + chunk.after = chunk.endTag + chunk.after; + + this.start = chunk.before.length; + this.end = chunk.before.length + chunk.selection.length; + this.text = chunk.before + chunk.selection + chunk.after; + this.scrollTop = chunk.scrollTop; + }; + this.init(); + }; + + function PreviewManager(converter, panels, previewRefreshCallback) { + + var managerObj = this; + var timeout; + var elapsedTime; + var oldInputText; + var maxDelay = 3000; + var startType = "delayed"; // The other legal value is "manual" + + // Adds event listeners to elements + var setupEvents = function (inputElem, listener) { + + util.addEvent(inputElem, "input", listener); + inputElem.onpaste = listener; + inputElem.ondrop = listener; + + util.addEvent(inputElem, "keypress", listener); + util.addEvent(inputElem, "keydown", listener); + }; + + var getDocScrollTop = function () { + + var result = 0; + + if (window.innerHeight) { + result = window.pageYOffset; + } + else + if (doc.documentElement && doc.documentElement.scrollTop) { + result = doc.documentElement.scrollTop; + } + else + if (doc.body) { + result = doc.body.scrollTop; + } + + return result; + }; + + var makePreviewHtml = function () { + + // If there is no registered preview panel + // there is nothing to do. + if (!panels.preview) + return; + + + var text = panels.input.value; + if (text && text == oldInputText) { + return; // Input text hasn't changed. + } + else { + oldInputText = text; + } + + var prevTime = new Date().getTime(); + + text = converter.makeHtml(text); + + // Calculate the processing time of the HTML creation. + // It's used as the delay time in the event listener. + var currTime = new Date().getTime(); + elapsedTime = currTime - prevTime; + + pushPreviewHtml(text); + }; + + // setTimeout is already used. Used as an event listener. + var applyTimeout = function () { + + if (timeout) { + clearTimeout(timeout); + timeout = undefined; + } + + if (startType !== "manual") { + + var delay = 0; + + if (startType === "delayed") { + delay = elapsedTime; + } + + if (delay > maxDelay) { + delay = maxDelay; + } + timeout = setTimeout(makePreviewHtml, delay); + } + }; + + var getScaleFactor = function (panel) { + if (panel.scrollHeight <= panel.clientHeight) { + return 1; + } + return panel.scrollTop / (panel.scrollHeight - panel.clientHeight); + }; + + var setPanelScrollTops = function () { + if (panels.preview) { + panels.preview.scrollTop = (panels.preview.scrollHeight - panels.preview.clientHeight) * getScaleFactor(panels.preview); + } + }; + + this.refresh = function (requiresRefresh) { + + if (requiresRefresh) { + oldInputText = ""; + makePreviewHtml(); + } + else { + applyTimeout(); + } + }; + + this.processingTime = function () { + return elapsedTime; + }; + + var isFirstTimeFilled = true; + + // IE doesn't let you use innerHTML if the element is contained somewhere in a table + // (which is the case for inline editing) -- in that case, detach the element, set the + // value, and reattach. Yes, that *is* ridiculous. + var ieSafePreviewSet = function (text) { + var preview = panels.preview; + var parent = preview.parentNode; + var sibling = preview.nextSibling; + parent.removeChild(preview); + preview.innerHTML = text; + if (!sibling) + parent.appendChild(preview); + else + parent.insertBefore(preview, sibling); + } + + var nonSuckyBrowserPreviewSet = function (text) { + panels.preview.innerHTML = text; + } + + var previewSetter; + + var previewSet = function (text) { + if (previewSetter) + return previewSetter(text); + + try { + nonSuckyBrowserPreviewSet(text); + previewSetter = nonSuckyBrowserPreviewSet; + } catch (e) { + previewSetter = ieSafePreviewSet; + previewSetter(text); + } + }; + + var pushPreviewHtml = function (text) { + + var emptyTop = position.getTop(panels.input) - getDocScrollTop(); + + if (panels.preview) { + previewSet(text); + previewRefreshCallback(); + } + + setPanelScrollTops(); + + if (isFirstTimeFilled) { + isFirstTimeFilled = false; + return; + } + + var fullTop = position.getTop(panels.input) - getDocScrollTop(); + + if (uaSniffed.isIE) { + setTimeout(function () { + window.scrollBy(0, fullTop - emptyTop); + }, 0); + } + else { + window.scrollBy(0, fullTop - emptyTop); + } + }; + + var init = function () { + + setupEvents(panels.input, applyTimeout); + makePreviewHtml(); + + if (panels.preview) { + panels.preview.scrollTop = 0; + } + }; + + init(); + }; + + // Creates the background behind the hyperlink text entry box. + // And download dialog + // Most of this has been moved to CSS but the div creation and + // browser-specific hacks remain here. + ui.createBackground = function () { + + var background = doc.createElement("div"); + background.className = "wmd-prompt-background"; + style = background.style; + style.position = "absolute"; + style.top = "0"; + + style.zIndex = "1000"; + + if (uaSniffed.isIE) { + style.filter = "alpha(opacity=50)"; + } + else { + style.opacity = "0.5"; + } + + var pageSize = position.getPageSize(); + style.height = pageSize[1] + "px"; + + if (uaSniffed.isIE) { + style.left = doc.documentElement.scrollLeft; + style.width = doc.documentElement.clientWidth; + } + else { + style.left = "0"; + style.width = "100%"; + } + + doc.body.appendChild(background); + return background; + }; + + // This simulates a modal dialog box and asks for the URL when you + // click the hyperlink or image buttons. + // + // text: The html for the input box. + // defaultInputText: The default value that appears in the input box. + // callback: The function which is executed when the prompt is dismissed, either via OK or Cancel. + // It receives a single argument; either the entered text (if OK was chosen) or null (if Cancel + // was chosen). + ui.prompt = function (text, defaultInputText, callback) { + + // These variables need to be declared at this level since they are used + // in multiple functions. + var dialog; // The dialog box. + var input; // The text box where you enter the hyperlink. + + + if (defaultInputText === undefined) { + defaultInputText = ""; + } + + // Used as a keydown event handler. Esc dismisses the prompt. + // Key code 27 is ESC. + var checkEscape = function (key) { + var code = (key.charCode || key.keyCode); + if (code === 27) { + close(true); + } + }; + + // Dismisses the hyperlink input box. + // isCancel is true if we don't care about the input text. + // isCancel is false if we are going to keep the text. + var close = function (isCancel) { + util.removeEvent(doc.body, "keydown", checkEscape); + var text = input.value; + + if (isCancel) { + text = null; + } + else { + // Fixes common pasting errors. + text = text.replace('http://http://', 'http://'); + text = text.replace('http://https://', 'https://'); + text = text.replace('http://ftp://', 'ftp://'); + + if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1 && text.indexOf('https://') === -1) { + text = 'http://' + text; + } + } + + dialog.parentNode.removeChild(dialog); + + callback(text); + return false; + }; + + + + // Create the text input box form/window. + var createDialog = function () { + + // The main dialog box. + dialog = doc.createElement("div"); + dialog.className = "wmd-prompt-dialog"; + dialog.style.padding = "10px;"; + dialog.style.position = "fixed"; + dialog.style.width = "400px"; + dialog.style.zIndex = "1001"; + + // The dialog text. + var question = doc.createElement("div"); + question.innerHTML = text; + question.style.padding = "5px"; + dialog.appendChild(question); + + // The web form container for the text box and buttons. + var form = doc.createElement("form"); + form.onsubmit = function () { return close(false); }; + style = form.style; + style.padding = "0"; + style.margin = "0"; + style.cssFloat = "left"; + style.width = "100%"; + style.textAlign = "center"; + style.position = "relative"; + dialog.appendChild(form); + + // The input text box + input = doc.createElement("input"); + input.type = "text"; + input.value = defaultInputText; + style = input.style; + style.display = "block"; + style.width = "80%"; + style.marginLeft = style.marginRight = "auto"; + form.appendChild(input); + + // The ok button + var okButton = doc.createElement("input"); + okButton.type = "button"; + okButton.onclick = function () { return close(false); }; + okButton.value = "OK"; + style = okButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + + // The cancel button + var cancelButton = doc.createElement("input"); + cancelButton.type = "button"; + cancelButton.onclick = function () { return close(true); }; + cancelButton.value = "Cancel"; + style = cancelButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + form.appendChild(okButton); + form.appendChild(cancelButton); + + util.addEvent(doc.body, "keydown", checkEscape); + dialog.style.top = "50%"; + dialog.style.left = "50%"; + dialog.style.display = "block"; + if (uaSniffed.isIE_5or6) { + dialog.style.position = "absolute"; + dialog.style.top = doc.documentElement.scrollTop + 200 + "px"; + dialog.style.left = "50%"; + } + doc.body.appendChild(dialog); + + // This has to be done AFTER adding the dialog to the form if you + // want it to be centered. + dialog.style.marginTop = -(position.getHeight(dialog) / 2) + "px"; + dialog.style.marginLeft = -(position.getWidth(dialog) / 2) + "px"; + + }; + + // Why is this in a zero-length timeout? + // Is it working around a browser bug? + setTimeout(function () { + + createDialog(); + + var defTextLen = defaultInputText.length; + if (input.selectionStart !== undefined) { + input.selectionStart = 0; + input.selectionEnd = defTextLen; + } + else if (input.createTextRange) { + var range = input.createTextRange(); + range.collapse(false); + range.moveStart("character", -defTextLen); + range.moveEnd("character", defTextLen); + range.select(); + } + + input.focus(); + }, 0); + }; + + function UIManager(postfix, panels, undoManager, previewManager, commandManager, helpOptions) { + + var inputBox = panels.input, + buttons = {}; // buttons.undo, buttons.link, etc. The actual DOM elements. + + makeSpritedButtonRow(); + + var keyEvent = "keydown"; + if (uaSniffed.isOpera) { + keyEvent = "keypress"; + } + + util.addEvent(inputBox, keyEvent, function (key) { + + // Check to see if we have a button key and, if so execute the callback. + if ((key.ctrlKey || key.metaKey) && !key.altKey) { + + var keyCode = key.charCode || key.keyCode; + var keyCodeStr = String.fromCharCode(keyCode).toLowerCase(); + + switch (keyCodeStr) { + case "b": + doClick(buttons.bold); + break; + case "i": + doClick(buttons.italic); + break; + case "l": + doClick(buttons.link); + break; + case "q": + doClick(buttons.quote); + break; + case "k": + doClick(buttons.code); + break; + case "g": + doClick(buttons.image); + break; + case "o": + doClick(buttons.olist); + break; + case "u": + doClick(buttons.ulist); + break; + case "h": + doClick(buttons.heading); + break; + case "r": + doClick(buttons.hr); + break; + case "y": + doClick(buttons.redo); + break; + case "z": + if (key.shiftKey) { + doClick(buttons.redo); + } + else { + doClick(buttons.undo); + } + break; + default: + return; + } + + + if (key.preventDefault) { + key.preventDefault(); + } + + if (window.event) { + window.event.returnValue = false; + } + } + }); + + // Auto-indent on shift-enter + util.addEvent(inputBox, "keyup", function (key) { + if (key.shiftKey && !key.ctrlKey && !key.metaKey) { + var keyCode = key.charCode || key.keyCode; + // Character 13 is Enter + if (keyCode === 13) { + fakeButton = {}; + fakeButton.textOp = bindCommand("doAutoindent"); + doClick(fakeButton); + } + } + }); + + // special handler because IE clears the context of the textbox on ESC + if (uaSniffed.isIE) { + util.addEvent(inputBox, "keydown", function (key) { + var code = key.keyCode; + if (code === 27) { + return false; + } + }); + } + + + // Perform the button's action. + function doClick(button) { + + inputBox.focus(); + + if (button.textOp) { + + if (undoManager) { + undoManager.setCommandMode(); + } + + var state = new TextareaState(panels); + + if (!state) { + return; + } + + var chunks = state.getChunks(); + + // Some commands launch a "modal" prompt dialog. Javascript + // can't really make a modal dialog box and the WMD code + // will continue to execute while the dialog is displayed. + // This prevents the dialog pattern I'm used to and means + // I can't do something like this: + // + // var link = CreateLinkDialog(); + // makeMarkdownLink(link); + // + // Instead of this straightforward method of handling a + // dialog I have to pass any code which would execute + // after the dialog is dismissed (e.g. link creation) + // in a function parameter. + // + // Yes this is awkward and I think it sucks, but there's + // no real workaround. Only the image and link code + // create dialogs and require the function pointers. + var fixupInputArea = function () { + + inputBox.focus(); + + if (chunks) { + state.setChunks(chunks); + } + + state.restore(); + previewManager.refresh(); + }; + + var noCleanup = button.textOp(chunks, fixupInputArea); + + if (!noCleanup) { + fixupInputArea(); + } + + } + + if (button.execute) { + button.execute(undoManager); + } + }; + + function setupButton(button, isEnabled) { + + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + var image = button.getElementsByTagName("span")[0]; + if (isEnabled) { + image.style.backgroundPosition = button.XShift + " " + normalYShift; + button.onmouseover = function () { + image.style.backgroundPosition = this.XShift + " " + highlightYShift; + }; + + button.onmouseout = function () { + image.style.backgroundPosition = this.XShift + " " + normalYShift; + }; + + // IE tries to select the background image "button" text (it's + // implemented in a list item) so we have to cache the selection + // on mousedown. + if (uaSniffed.isIE) { + button.onmousedown = function () { + if (doc.activeElement && doc.activeElement !== panels.input) { // we're not even in the input box, so there's no selection + return; + } + panels.ieCachedRange = document.selection.createRange(); + panels.ieCachedScrollTop = panels.input.scrollTop; + }; + } + + if (!button.isHelp) { + button.onclick = function () { + if (this.onmouseout) { + this.onmouseout(); + } + doClick(this); + return false; + } + } + } + else { + image.style.backgroundPosition = button.XShift + " " + disabledYShift; + button.onmouseover = button.onmouseout = button.onclick = function () { }; + } + } + + function bindCommand(method) { + if (typeof method === "string") + method = commandManager[method]; + return function () { method.apply(commandManager, arguments); } + } + + function makeSpritedButtonRow() { + + var buttonBar = panels.buttonBar; + + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + + var buttonRow = document.createElement("ul"); + buttonRow.id = "wmd-button-row" + postfix; + buttonRow.className = 'wmd-button-row'; + buttonRow = buttonBar.appendChild(buttonRow); + var xPosition = 0; + var makeButton = function (id, title, XShift, textOp) { + var button = document.createElement("li"); + button.className = "wmd-button"; + button.style.left = xPosition + "px"; + xPosition += 25; + var buttonImage = document.createElement("span"); + button.id = id + postfix; + button.appendChild(buttonImage); + button.title = title; + button.XShift = XShift; + if (textOp) + button.textOp = textOp; + setupButton(button, true); + buttonRow.appendChild(button); + return button; + }; + var makeSpacer = function (num) { + var spacer = document.createElement("li"); + spacer.className = "wmd-spacer wmd-spacer" + num; + spacer.id = "wmd-spacer" + num + postfix; + buttonRow.appendChild(spacer); + xPosition += 25; + } + + buttons.bold = makeButton("wmd-bold-button", "Strong Ctrl+B", "0px", bindCommand("doBold")); + buttons.italic = makeButton("wmd-italic-button", "Emphasis Ctrl+I", "-20px", bindCommand("doItalic")); + makeSpacer(1); + buttons.link = makeButton("wmd-link-button", "Hyperlink Ctrl+L", "-40px", bindCommand(function (chunk, postProcessing) { + return this.doLinkOrImage(chunk, postProcessing, false); + })); + buttons.quote = makeButton("wmd-quote-button", "Blockquote
    Ctrl+Q", "-60px", bindCommand("doBlockquote")); + buttons.code = makeButton("wmd-code-button", "Code Sample
     Ctrl+K", "-80px", bindCommand("doCode"));
    +            buttons.image = makeButton("wmd-image-button", "Image  Ctrl+G", "-100px", bindCommand(function (chunk, postProcessing) {
    +                return this.doLinkOrImage(chunk, postProcessing, true);
    +            }));
    +            makeSpacer(2);
    +            buttons.olist = makeButton("wmd-olist-button", "Numbered List 
      Ctrl+O", "-120px", bindCommand(function (chunk, postProcessing) { + this.doList(chunk, postProcessing, true); + })); + buttons.ulist = makeButton("wmd-ulist-button", "Bulleted List
        Ctrl+U", "-140px", bindCommand(function (chunk, postProcessing) { + this.doList(chunk, postProcessing, false); + })); + buttons.heading = makeButton("wmd-heading-button", "Heading

        /

        Ctrl+H", "-160px", bindCommand("doHeading")); + buttons.hr = makeButton("wmd-hr-button", "Horizontal Rule
        Ctrl+R", "-180px", bindCommand("doHorizontalRule")); + makeSpacer(3); + buttons.undo = makeButton("wmd-undo-button", "Undo - Ctrl+Z", "-200px", null); + buttons.undo.execute = function (manager) { if (manager) manager.undo(); }; + + var redoTitle = /win/.test(nav.platform.toLowerCase()) ? + "Redo - Ctrl+Y" : + "Redo - Ctrl+Shift+Z"; // mac and other non-Windows platforms + + buttons.redo = makeButton("wmd-redo-button", redoTitle, "-220px", null); + buttons.redo.execute = function (manager) { if (manager) manager.redo(); }; + + if (helpOptions) { + var helpButton = document.createElement("li"); + var helpButtonImage = document.createElement("span"); + helpButton.appendChild(helpButtonImage); + helpButton.className = "wmd-button wmd-help-button"; + helpButton.id = "wmd-help-button" + postfix; + helpButton.XShift = "-240px"; + helpButton.isHelp = true; + helpButton.style.right = "0px"; + helpButton.title = helpOptions.title || defaultHelpHoverTitle; + helpButton.onclick = helpOptions.handler; + + setupButton(helpButton, true); + buttonRow.appendChild(helpButton); + buttons.help = helpButton; + } + + setUndoRedoButtonStates(); + } + + function setUndoRedoButtonStates() { + if (undoManager) { + setupButton(buttons.undo, undoManager.canUndo()); + setupButton(buttons.redo, undoManager.canRedo()); + } + }; + + this.setUndoRedoButtonStates = setUndoRedoButtonStates; + + } + + function CommandManager(pluginHooks) { + this.hooks = pluginHooks; + } + + var commandProto = CommandManager.prototype; + + // The markdown symbols - 4 spaces = code, > = blockquote, etc. + commandProto.prefixes = "(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)"; + + // Remove markdown symbols from the chunk selection. + commandProto.unwrap = function (chunk) { + var txt = new re("([^\\n])\\n(?!(\\n|" + this.prefixes + "))", "g"); + chunk.selection = chunk.selection.replace(txt, "$1 $2"); + }; + + commandProto.wrap = function (chunk, len) { + this.unwrap(chunk); + var regex = new re("(.{1," + len + "})( +|$\\n?)", "gm"); + + chunk.selection = chunk.selection.replace(regex, function (line, marked) { + if (new re("^" + this.prefixes, "").test(line)) { + return line; + } + return marked + "\n"; + }); + + chunk.selection = chunk.selection.replace(/\s+$/, ""); + }; + + commandProto.doBold = function (chunk, postProcessing) { + return this.doBorI(chunk, postProcessing, 2, "strong text"); + }; + + commandProto.doItalic = function (chunk, postProcessing) { + return this.doBorI(chunk, postProcessing, 1, "emphasized text"); + }; + + // chunk: The selected region that will be enclosed with */** + // nStars: 1 for italics, 2 for bold + // insertText: If you just click the button without highlighting text, this gets inserted + commandProto.doBorI = function (chunk, postProcessing, nStars, insertText) { + + // Get rid of whitespace and fixup newlines. + chunk.trimWhitespace(); + chunk.selection = chunk.selection.replace(/\n{2,}/g, "\n"); + + // Look for stars before and after. Is the chunk already marked up? + // note that these regex matches cannot fail + var starsBefore = /(\**$)/.exec(chunk.before)[0]; + var starsAfter = /(^\**)/.exec(chunk.after)[0]; + + var prevStars = Math.min(starsBefore.length, starsAfter.length); + + // Remove stars if we have to since the button acts as a toggle. + if ((prevStars >= nStars) && (prevStars != 2 || nStars != 1)) { + chunk.before = chunk.before.replace(re("[*]{" + nStars + "}$", ""), ""); + chunk.after = chunk.after.replace(re("^[*]{" + nStars + "}", ""), ""); + } + else if (!chunk.selection && starsAfter) { + // It's not really clear why this code is necessary. It just moves + // some arbitrary stuff around. + chunk.after = chunk.after.replace(/^([*_]*)/, ""); + chunk.before = chunk.before.replace(/(\s?)$/, ""); + var whitespace = re.$1; + chunk.before = chunk.before + starsAfter + whitespace; + } + else { + + // In most cases, if you don't have any selected text and click the button + // you'll get a selected, marked up region with the default text inserted. + if (!chunk.selection && !starsAfter) { + chunk.selection = insertText; + } + + // Add the true markup. + var markup = nStars <= 1 ? "*" : "**"; // shouldn't the test be = ? + chunk.before = chunk.before + markup; + chunk.after = markup + chunk.after; + } + + return; + }; + + commandProto.stripLinkDefs = function (text, defsToAdd) { + + text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm, + function (totalMatch, id, link, newlines, title) { + defsToAdd[id] = totalMatch.replace(/\s*$/, ""); + if (newlines) { + // Strip the title and return that separately. + defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, ""); + return newlines + title; + } + return ""; + }); + + return text; + }; + + commandProto.addLinkDef = function (chunk, linkDef) { + + var refNumber = 0; // The current reference number + var defsToAdd = {}; // + // Start with a clean slate by removing all previous link definitions. + chunk.before = this.stripLinkDefs(chunk.before, defsToAdd); + chunk.selection = this.stripLinkDefs(chunk.selection, defsToAdd); + chunk.after = this.stripLinkDefs(chunk.after, defsToAdd); + + var defs = ""; + var regex = /(\[)((?:\[[^\]]*\]|[^\[\]])*)(\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g; + + var addDefNumber = function (def) { + refNumber++; + def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, " [" + refNumber + "]:"); + defs += "\n" + def; + }; + + // note that + // a) the recursive call to getLink cannot go infinite, because by definition + // of regex, inner is always a proper substring of wholeMatch, and + // b) more than one level of nesting is neither supported by the regex + // nor making a lot of sense (the only use case for nesting is a linked image) + var getLink = function (wholeMatch, before, inner, afterInner, id, end) { + inner = inner.replace(regex, getLink); + if (defsToAdd[id]) { + addDefNumber(defsToAdd[id]); + return before + inner + afterInner + refNumber + end; + } + return wholeMatch; + }; + + chunk.before = chunk.before.replace(regex, getLink); + + if (linkDef) { + addDefNumber(linkDef); + } + else { + chunk.selection = chunk.selection.replace(regex, getLink); + } + + var refOut = refNumber; + + chunk.after = chunk.after.replace(regex, getLink); + + if (chunk.after) { + chunk.after = chunk.after.replace(/\n*$/, ""); + } + if (!chunk.after) { + chunk.selection = chunk.selection.replace(/\n*$/, ""); + } + + chunk.after += "\n\n" + defs; + + return refOut; + }; + + // takes the line as entered into the add link/as image dialog and makes + // sure the URL and the optinal title are "nice". + function properlyEncoded(linkdef) { + return linkdef.replace(/^\s*(.*?)(?:\s+"(.+)")?\s*$/, function (wholematch, link, title) { + link = link.replace(/\?.*$/, function (querypart) { + return querypart.replace(/\+/g, " "); // in the query string, a plus and a space are identical + }); + link = decodeURIComponent(link); // unencode first, to prevent double encoding + link = encodeURI(link).replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29'); + link = link.replace(/\?.*$/, function (querypart) { + return querypart.replace(/\+/g, "%2b"); // since we replaced plus with spaces in the query part, all pluses that now appear where originally encoded + }); + if (title) { + title = title.trim ? title.trim() : title.replace(/^\s*/, "").replace(/\s*$/, ""); + title = $.trim(title).replace(/"/g, "quot;").replace(/\(/g, "(").replace(/\)/g, ")").replace(//g, ">"); + } + return title ? link + ' "' + title + '"' : link; + }); + } + + commandProto.doLinkOrImage = function (chunk, postProcessing, isImage) { + + chunk.trimWhitespace(); + chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/); + var background; + + if (chunk.endTag.length > 1) { + + chunk.startTag = chunk.startTag.replace(/!?\[/, ""); + chunk.endTag = ""; + this.addLinkDef(chunk, null); + + } + else { + + if (/\n\n/.test(chunk.selection)) { + this.addLinkDef(chunk, null); + return; + } + var that = this; + // The function to be executed when you enter a link and press OK or Cancel. + // Marks up the link and adds the ref. + var linkEnteredCallback = function (link) { + + background.parentNode.removeChild(background); + + if (link !== null) { + + chunk.startTag = chunk.endTag = ""; + var linkDef = " [999]: " + properlyEncoded(link); + + var num = that.addLinkDef(chunk, linkDef); + chunk.startTag = isImage ? "![" : "["; + chunk.endTag = "][" + num + "]"; + + if (!chunk.selection) { + if (isImage) { + chunk.selection = "enter image description here"; + } + else { + chunk.selection = "enter link description here"; + } + } + } + postProcessing(); + }; + + background = ui.createBackground(); + + if (isImage) { + if (!this.hooks.insertImageDialog(linkEnteredCallback)) + ui.prompt(imageDialogText, imageDefaultText, linkEnteredCallback); + } + else { + ui.prompt(linkDialogText, linkDefaultText, linkEnteredCallback); + } + return true; + } + }; + + // When making a list, hitting shift-enter will put your cursor on the next line + // at the current indent level. + commandProto.doAutoindent = function (chunk, postProcessing) { + + var commandMgr = this; + + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ \t]+\n$/, "\n\n"); + + if (/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(chunk.before)) { + if (commandMgr.doList) { + commandMgr.doList(chunk); + } + } + if (/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(chunk.before)) { + if (commandMgr.doBlockquote) { + commandMgr.doBlockquote(chunk); + } + } + if (/(\n|^)(\t|[ ]{4,}).*\n$/.test(chunk.before)) { + if (commandMgr.doCode) { + commandMgr.doCode(chunk); + } + } + }; + + commandProto.doBlockquote = function (chunk, postProcessing) { + + chunk.selection = chunk.selection.replace(/^(\n*)([^\r]+?)(\n*)$/, + function (totalMatch, newlinesBefore, text, newlinesAfter) { + chunk.before += newlinesBefore; + chunk.after = newlinesAfter + chunk.after; + return text; + }); + + chunk.before = chunk.before.replace(/(>[ \t]*)$/, + function (totalMatch, blankLine) { + chunk.selection = blankLine + chunk.selection; + return ""; + }); + + chunk.selection = chunk.selection.replace(/^(\s|>)+$/, ""); + chunk.selection = chunk.selection || "Blockquote"; + + // The original code uses a regular expression to find out how much of the + // text *directly before* the selection already was a blockquote: + + /* + if (chunk.before) { + chunk.before = chunk.before.replace(/\n?$/, "\n"); + } + chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/, + function (totalMatch) { + chunk.startTag = totalMatch; + return ""; + }); + */ + + // This comes down to: + // Go backwards as many lines a possible, such that each line + // a) starts with ">", or + // b) is almost empty, except for whitespace, or + // c) is preceeded by an unbroken chain of non-empty lines + // leading up to a line that starts with ">" and at least one more character + // and in addition + // d) at least one line fulfills a) + // + // Since this is essentially a backwards-moving regex, it's susceptible to + // catstrophic backtracking and can cause the browser to hang; + // see e.g. http://meta.stackoverflow.com/questions/9807. + // + // Hence we replaced this by a simple state machine that just goes through the + // lines and checks for a), b), and c). + + var match = "", + leftOver = "", + line; + if (chunk.before) { + var lines = chunk.before.replace(/\n$/, "").split("\n"); + var inChain = false; + for (var i = 0; i < lines.length; i++) { + var good = false; + line = lines[i]; + inChain = inChain && line.length > 0; // c) any non-empty line continues the chain + if (/^>/.test(line)) { // a) + good = true; + if (!inChain && line.length > 1) // c) any line that starts with ">" and has at least one more character starts the chain + inChain = true; + } else if (/^[ \t]*$/.test(line)) { // b) + good = true; + } else { + good = inChain; // c) the line is not empty and does not start with ">", so it matches if and only if we're in the chain + } + if (good) { + match += line + "\n"; + } else { + leftOver += match + line; + match = "\n"; + } + } + if (!/(^|\n)>/.test(match)) { // d) + leftOver += match; + match = ""; + } + } + + chunk.startTag = match; + chunk.before = leftOver; + + // end of change + + if (chunk.after) { + chunk.after = chunk.after.replace(/^\n?/, "\n"); + } + + chunk.after = chunk.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/, + function (totalMatch) { + chunk.endTag = totalMatch; + return ""; + } + ); + + var replaceBlanksInTags = function (useBracket) { + + var replacement = useBracket ? "> " : ""; + + if (chunk.startTag) { + chunk.startTag = chunk.startTag.replace(/\n((>|\s)*)\n$/, + function (totalMatch, markdown) { + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + if (chunk.endTag) { + chunk.endTag = chunk.endTag.replace(/^\n((>|\s)*)\n/, + function (totalMatch, markdown) { + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + }; + + if (/^(?![ ]{0,3}>)/m.test(chunk.selection)) { + this.wrap(chunk, SETTINGS.lineLength - 2); + chunk.selection = chunk.selection.replace(/^/gm, "> "); + replaceBlanksInTags(true); + chunk.skipLines(); + } else { + chunk.selection = chunk.selection.replace(/^[ ]{0,3}> ?/gm, ""); + this.unwrap(chunk); + replaceBlanksInTags(false); + + if (!/^(\n|^)[ ]{0,3}>/.test(chunk.selection) && chunk.startTag) { + chunk.startTag = chunk.startTag.replace(/\n{0,2}$/, "\n\n"); + } + + if (!/(\n|^)[ ]{0,3}>.*$/.test(chunk.selection) && chunk.endTag) { + chunk.endTag = chunk.endTag.replace(/^\n{0,2}/, "\n\n"); + } + } + + chunk.selection = this.hooks.postBlockquoteCreation(chunk.selection); + + if (!/\n/.test(chunk.selection)) { + chunk.selection = chunk.selection.replace(/^(> *)/, + function (wholeMatch, blanks) { + chunk.startTag += blanks; + return ""; + }); + } + }; + + commandProto.doCode = function (chunk, postProcessing) { + + var hasTextBefore = /\S[ ]*$/.test(chunk.before); + var hasTextAfter = /^[ ]*\S/.test(chunk.after); + + // Use 'four space' markdown if the selection is on its own + // line or is multiline. + if ((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)) { + + chunk.before = chunk.before.replace(/[ ]{4}$/, + function (totalMatch) { + chunk.selection = totalMatch + chunk.selection; + return ""; + }); + + var nLinesBack = 1; + var nLinesForward = 1; + + if (/\n(\t|[ ]{4,}).*\n$/.test(chunk.before)) { + nLinesBack = 0; + } + if (/^\n(\t|[ ]{4,})/.test(chunk.after)) { + nLinesForward = 0; + } + + chunk.skipLines(nLinesBack, nLinesForward); + + if (!chunk.selection) { + chunk.startTag = " "; + chunk.selection = "enter code here"; + } + else { + if (/^[ ]{0,3}\S/m.test(chunk.selection)) { + chunk.selection = chunk.selection.replace(/^/gm, " "); + } + else { + chunk.selection = chunk.selection.replace(/^[ ]{4}/gm, ""); + } + } + } + else { + // Use backticks (`) to delimit the code block. + + chunk.trimWhitespace(); + chunk.findTags(/`/, /`/); + + if (!chunk.startTag && !chunk.endTag) { + chunk.startTag = chunk.endTag = "`"; + if (!chunk.selection) { + chunk.selection = "enter code here"; + } + } + else if (chunk.endTag && !chunk.startTag) { + chunk.before += chunk.endTag; + chunk.endTag = ""; + } + else { + chunk.startTag = chunk.endTag = ""; + } + } + }; + + commandProto.doList = function (chunk, postProcessing, isNumberedList) { + + // These are identical except at the very beginning and end. + // Should probably use the regex extension function to make this clearer. + var previousItemsRegex = /(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/; + var nextItemsRegex = /^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/; + + // The default bullet is a dash but others are possible. + // This has nothing to do with the particular HTML bullet, + // it's just a markdown bullet. + var bullet = "-"; + + // The number in a numbered list. + var num = 1; + + // Get the item prefix - e.g. " 1. " for a numbered list, " - " for a bulleted list. + var getItemPrefix = function () { + var prefix; + if (isNumberedList) { + prefix = " " + num + ". "; + num++; + } + else { + prefix = " " + bullet + " "; + } + return prefix; + }; + + // Fixes the prefixes of the other list items. + var getPrefixedItem = function (itemText) { + + // The numbering flag is unset when called by autoindent. + if (isNumberedList === undefined) { + isNumberedList = /^\s*\d/.test(itemText); + } + + // Renumber/bullet the list element. + itemText = itemText.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm, + function (_) { + return getItemPrefix(); + }); + + return itemText; + }; + + chunk.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/, null); + + if (chunk.before && !/\n$/.test(chunk.before) && !/^\n/.test(chunk.startTag)) { + chunk.before += chunk.startTag; + chunk.startTag = ""; + } + + if (chunk.startTag) { + + var hasDigits = /\d+[.]/.test(chunk.startTag); + chunk.startTag = ""; + chunk.selection = chunk.selection.replace(/\n[ ]{4}/g, "\n"); + this.unwrap(chunk); + chunk.skipLines(); + + if (hasDigits) { + // Have to renumber the bullet points if this is a numbered list. + chunk.after = chunk.after.replace(nextItemsRegex, getPrefixedItem); + } + if (isNumberedList == hasDigits) { + return; + } + } + + var nLinesUp = 1; + + chunk.before = chunk.before.replace(previousItemsRegex, + function (itemText) { + if (/^\s*([*+-])/.test(itemText)) { + bullet = re.$1; + } + nLinesUp = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + if (!chunk.selection) { + chunk.selection = "List item"; + } + + var prefix = getItemPrefix(); + + var nLinesDown = 1; + + chunk.after = chunk.after.replace(nextItemsRegex, + function (itemText) { + nLinesDown = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + chunk.trimWhitespace(true); + chunk.skipLines(nLinesUp, nLinesDown, true); + chunk.startTag = prefix; + var spaces = prefix.replace(/./g, " "); + this.wrap(chunk, SETTINGS.lineLength - spaces.length); + chunk.selection = chunk.selection.replace(/\n/g, "\n" + spaces); + + }; + + commandProto.doHeading = function (chunk, postProcessing) { + + // Remove leading/trailing whitespace and reduce internal spaces to single spaces. + chunk.selection = chunk.selection.replace(/\s+/g, " "); + chunk.selection = chunk.selection.replace(/(^\s+|\s+$)/g, ""); + + // If we clicked the button with no selected text, we just + // make a level 2 hash header around some default text. + if (!chunk.selection) { + chunk.startTag = "## "; + chunk.selection = "Heading"; + chunk.endTag = " ##"; + return; + } + + var headerLevel = 0; // The existing header level of the selected text. + + // Remove any existing hash heading markdown and save the header level. + chunk.findTags(/#+[ ]*/, /[ ]*#+/); + if (/#+/.test(chunk.startTag)) { + headerLevel = re.lastMatch.length; + } + chunk.startTag = chunk.endTag = ""; + + // Try to get the current header level by looking for - and = in the line + // below the selection. + chunk.findTags(null, /\s?(-+|=+)/); + if (/=+/.test(chunk.endTag)) { + headerLevel = 1; + } + if (/-+/.test(chunk.endTag)) { + headerLevel = 2; + } + + // Skip to the next line so we can create the header markdown. + chunk.startTag = chunk.endTag = ""; + chunk.skipLines(1, 1); + + // We make a level 2 header if there is no current header. + // If there is a header level, we substract one from the header level. + // If it's already a level 1 header, it's removed. + var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1; + + if (headerLevelToCreate > 0) { + + // The button only creates level 1 and 2 underline headers. + // Why not have it iterate over hash header levels? Wouldn't that be easier and cleaner? + var headerChar = headerLevelToCreate >= 2 ? "-" : "="; + var len = chunk.selection.length; + if (len > SETTINGS.lineLength) { + len = SETTINGS.lineLength; + } + chunk.endTag = "\n"; + while (len--) { + chunk.endTag += headerChar; + } + } + }; + + commandProto.doHorizontalRule = function (chunk, postProcessing) { + chunk.startTag = "----------\n"; + chunk.selection = ""; + chunk.skipLines(2, 1, true); + } + + +})(); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Sanitizer.js b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Sanitizer.js new file mode 100644 index 000000000..cc5826fa8 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Scripts/Markdown.Sanitizer.js @@ -0,0 +1,108 @@ +(function () { + var output, Converter; + if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (e.g. Node.js) module + output = exports; + Converter = require("./Markdown.Converter").Converter; + } else { + output = window.Markdown; + Converter = output.Converter; + } + + output.getSanitizingConverter = function () { + var converter = new Converter(); + converter.hooks.chain("postConversion", sanitizeHtml); + converter.hooks.chain("postConversion", balanceTags); + return converter; + } + + function sanitizeHtml(html) { + return html.replace(/<[^>]*>?/gi, sanitizeTag); + } + + // (tags that can be opened/closed) | (tags that stand alone) + var basic_tag_whitelist = /^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i; + //
        | + var a_white = /^(]+")?\s?>|<\/a>)$/i; + + // ]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i; + + function sanitizeTag(tag) { + if (tag.match(basic_tag_whitelist) || tag.match(a_white) || tag.match(img_white)) + return tag; + else + return ""; + } + + /// + /// attempt to balance HTML tags in the html string + /// by removing any unmatched opening or closing tags + /// IMPORTANT: we *assume* HTML has *already* been + /// sanitized and is safe/sane before balancing! + /// + /// adapted from CODESNIPPET: A8591DBA-D1D3-11DE-947C-BA5556D89593 + /// + function balanceTags(html) { + + if (html == "") + return ""; + + var re = /<\/?\w+[^>]*(\s|$|>)/g; + // convert everything to lower case; this makes + // our case insensitive comparisons easier + var tags = html.toLowerCase().match(re); + + // no HTML tags present? nothing to do; exit now + var tagcount = (tags || []).length; + if (tagcount == 0) + return html; + + var tagname, tag; + var ignoredtags = "



      • "; + var match; + var tagpaired = []; + var tagremove = []; + var needsRemoval = false; + + // loop through matched tags in forward order + for (var ctag = 0; ctag < tagcount; ctag++) { + tagname = tags[ctag].replace(/<\/?(\w+).*/, "$1"); + // skip any already paired tags + // and skip tags in our ignore list; assume they're self-closed + if (tagpaired[ctag] || ignoredtags.search("<" + tagname + ">") > -1) + continue; + + tag = tags[ctag]; + match = -1; + + if (!/^<\//.test(tag)) { + // this is an opening tag + // search forwards (next tags), look for closing tags + for (var ntag = ctag + 1; ntag < tagcount; ntag++) { + if (!tagpaired[ntag] && tags[ntag] == "") { + match = ntag; + break; + } + } + } + + if (match == -1) + needsRemoval = tagremove[ctag] = true; // mark for removal + else + tagpaired[match] = true; // mark paired + } + + if (!needsRemoval) + return html; + + // delete all orphaned tags from the string + + var ctag = 0; + html = html.replace(re, function (match) { + var res = tagremove[ctag] ? "" : match; + ctag++; + return res; + }); + return html; + } +})(); diff --git a/src/Orchard.Web/Modules/Markdown/Scripts/Web.config b/src/Orchard.Web/Modules/Markdown/Scripts/Web.config new file mode 100644 index 000000000..df1c33504 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Scripts/Web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Markdown/Scripts/jquery.textarearesizer.min.js b/src/Orchard.Web/Modules/Markdown/Scripts/jquery.textarearesizer.min.js new file mode 100644 index 000000000..5464ae6b6 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Scripts/jquery.textarearesizer.min.js @@ -0,0 +1 @@ +(function($){var textarea,staticOffset;var iLastMousePos=0;var iMin=32;var grip;$.fn.TextAreaResizer=function(){return this.each(function(){textarea=$(this).addClass('processed'),staticOffset=null;$(this).wrap('
        ').parent().append($('
        ').bind("mousedown",{el:this},startDrag));var grippie=$('div.grippie',$(this).parent())[0];grippie.style.marginRight=(grippie.offsetWidth-$(this)[0].offsetWidth)+'px'})};function startDrag(e){textarea=$(e.data.el);textarea.blur();iLastMousePos=mousePosition(e).y;staticOffset=textarea.height()-iLastMousePos;textarea.css('opacity',0.25);$(document).mousemove(performDrag).mouseup(endDrag);return false}function performDrag(e){var iThisMousePos=mousePosition(e).y;var iMousePos=staticOffset+iThisMousePos;if(iLastMousePos>=(iThisMousePos)){iMousePos-=5}iLastMousePos=iThisMousePos;iMousePos=Math.max(iMin,iMousePos);textarea.height(iMousePos+'px');if(iMousePos with , so we can easily use jquery to get the 'src' without it + // being resolved by the browser (e.g. prevent '/foo.png' becoming 'http://localhost:12345/orchardlocal/foo.png'). + content = content.replace(/\ + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Markdown/Styles/admin-markdown.css b/src/Orchard.Web/Modules/Markdown/Styles/admin-markdown.css new file mode 100644 index 000000000..5cc806cca --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Styles/admin-markdown.css @@ -0,0 +1,88 @@ +.wmd-button { + width: 20px; + height: 20px; + padding-left: 2px; + padding-right: 3px; + position: absolute; + display: inline-block; + list-style: none; + cursor: pointer; +} + +.wmd-button > span { + background-image: url(../Content/Admin/Images/wmd-buttons.png); + background-repeat: no-repeat; + background-position: 0px 0px; + width: 20px; + height: 20px; + display: inline-block; +} + +.wmd-button-row +{ + position: relative; + margin-left: 5px; + margin-right: 5px; + margin-bottom: 5px; + margin-top: 10px; + padding: 0px; + height: 20px; +} + +.wmd-input { + font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif; + width: 660px; + padding: 3px; + height: 200px; + line-height: 1.2; +} + +.wmd-preview { + border: 2px dotted #CCC; + padding: 3px; + margin-top: 6px; +} + +.wmd-preview ol { + list-style: decimal; + margin-left: 15px; +} + +.wmd-preview ul { + list-style: disc; + margin-left: 15px; +} + +.wmd-preview blockquote { + margin: 1em 3em; + color: #999; + border-left: 2px solid #999; + padding-left: 1em; +} + +.wmd-preview pre, .wmd-preview code { + margin: 1em 3em; + color: #999; + border-left: 2px solid #999; + padding-left: 1em; + font-family: Courier New; +} + +/* Grippie */ + +div.grippie { + background:#EEEEEE url(../Content/Admin/Images/grippie.png) no-repeat scroll center 2px; + border-color:#DDDDDD; + border-style:solid; + border-width:0pt 1px 1px; + cursor:s-resize; + height:9px; + overflow:hidden; +} + +.resizable-textarea textarea { + display:block; + margin-bottom:0pt; + width:95%; + height: 20%; +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Markdown/Views/Body-Markdown.Editor.cshtml b/src/Orchard.Web/Modules/Markdown/Views/Body-Markdown.Editor.cshtml new file mode 100644 index 000000000..33e45f0eb --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Views/Body-Markdown.Editor.cshtml @@ -0,0 +1,20 @@ +@{ + Script.Require("OrchardMarkdown"); + Style.Require("OrchardMarkdown"); +} +
        +
        + +@Html.TextArea("Text", (string)Model.Text, 25, 80, + new Dictionary { + {"id", "wmd-input"}, + {"class", "wmd-input grippie"}, + {"data-mediapicker-uploadpath", Model.AddMediaPath}, + {"data-mediapicker-title", T("Insert/Update Media")} + }) +
        + +
        + +
        +
        diff --git a/src/Orchard.Web/Modules/Markdown/Views/Web.config b/src/Orchard.Web/Modules/Markdown/Views/Web.config new file mode 100644 index 000000000..b7d215131 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/Views/Web.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Markdown/web.config b/src/Orchard.Web/Modules/Markdown/web.config new file mode 100644 index 000000000..e58955367 --- /dev/null +++ b/src/Orchard.Web/Modules/Markdown/web.config @@ -0,0 +1,39 @@ + + + + + + + +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ArchiveLater/Module.txt b/src/Orchard.Web/Modules/Orchard.ArchiveLater/Module.txt index c039b383c..f902bd27a 100644 --- a/src/Orchard.Web/Modules/Orchard.ArchiveLater/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ArchiveLater/Module.txt @@ -3,8 +3,8 @@ Path: ArchiveLater AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The ArchiveLater module introduces scheduled archiving functionality. FeatureDescription: Scheduled archiving. Category: Content diff --git a/src/Orchard.Web/Modules/Orchard.ArchiveLater/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ArchiveLater/Properties/AssemblyInfo.cs index f6c0e0a4b..58824d344 100644 --- a/src/Orchard.Web/Modules/Orchard.ArchiveLater/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ArchiveLater/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs index b9424d266..0f93bf489 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs @@ -27,16 +27,16 @@ namespace Orchard.Blogs { if (blogCount > 0 && singleBlog == null) { menu.Add(T("Manage Blogs"), "3", - item => item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs)); + item => item.Action("List", "BlogAdmin", new { area = "Orchard.Blogs" }).Permission(Permissions.MetaListBlogs)); } else if (singleBlog != null) menu.Add(T("Manage Blog"), "1.0", - item => item.Action("Item", "BlogAdmin", new { area = "Orchard.Blogs", blogId = singleBlog.Id }).Permission(Permissions.MetaListBlogs)); + item => item.Action("Item", "BlogAdmin", new { area = "Orchard.Blogs", blogId = singleBlog.Id }).Permission(Permissions.MetaListOwnBlogs)); if (singleBlog != null) menu.Add(T("New Post"), "1.1", item => - item.Action("Create", "BlogPostAdmin", new { area = "Orchard.Blogs", blogId = singleBlog.Id }).Permission(Permissions.PublishBlogPost)); + item.Action("Create", "BlogPostAdmin", new { area = "Orchard.Blogs", blogId = singleBlog.Id }).Permission(Permissions.MetaListOwnBlogs)); menu.Add(T("New Blog"), "1.2", item => diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs index 416613b57..7f8a481ae 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs @@ -30,8 +30,6 @@ namespace Orchard.Blogs.Controllers { public Localizer T { get; set; } public ActionResult Create(int blogId) { - if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, T("Not allowed to create blog post"))) - return new HttpUnauthorizedResult(); var blog = _blogService.Get(blogId, VersionOptions.Latest).As(); if (blog == null) @@ -40,7 +38,11 @@ namespace Orchard.Blogs.Controllers { var blogPost = Services.ContentManager.New("BlogPost"); blogPost.BlogPart = blog; + if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blogPost, T("Not allowed to create blog post"))) + return new HttpUnauthorizedResult(); + dynamic model = Services.ContentManager.BuildEditor(blogPost); + // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation. return View((object)model); } @@ -48,32 +50,30 @@ namespace Orchard.Blogs.Controllers { [HttpPost, ActionName("Create")] [FormValueRequired("submit.Save")] public ActionResult CreatePOST(int blogId) { - return CreatePOST(blogId, contentItem => { - if (!contentItem.Has() && !contentItem.TypeDefinition.Settings.GetModel().Draftable) - Services.ContentManager.Publish(contentItem); - }); + return CreatePOST(blogId, false); } [HttpPost, ActionName("Create")] [FormValueRequired("submit.Publish")] public ActionResult CreateAndPublishPOST(int blogId) { - if (!Services.Authorizer.Authorize(Permissions.PublishBlogPost, T("Couldn't create blog post"))) + if (!Services.Authorizer.Authorize(Permissions.PublishOwnBlogPost, T("Couldn't create content"))) return new HttpUnauthorizedResult(); - return CreatePOST(blogId, contentItem => Services.ContentManager.Publish(contentItem)); + return CreatePOST(blogId, true); } - private ActionResult CreatePOST(int blogId, Action conditionallyPublish) { - if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, T("Couldn't create blog post"))) - return new HttpUnauthorizedResult(); - + private ActionResult CreatePOST(int blogId, bool publish = false) { var blog = _blogService.Get(blogId, VersionOptions.Latest).As(); + if (blog == null) return HttpNotFound(); var blogPost = Services.ContentManager.New("BlogPost"); blogPost.BlogPart = blog; + if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blogPost, T("Couldn't create blog post"))) + return new HttpUnauthorizedResult(); + Services.ContentManager.Create(blogPost, VersionOptions.Draft); var model = Services.ContentManager.UpdateEditor(blogPost, this); @@ -83,7 +83,12 @@ namespace Orchard.Blogs.Controllers { return View((object)model); } - conditionallyPublish(blogPost.ContentItem); + if (publish) { + if (!Services.Authorizer.Authorize(Permissions.PublishBlogPost, blog.ContentItem, T("Couldn't publish blog post"))) + return new HttpUnauthorizedResult(); + + Services.ContentManager.Publish(blogPost.ContentItem); + } Services.Notifier.Information(T("Your {0} has been created.", blogPost.TypeDefinition.DisplayName)); return Redirect(Url.BlogPostEdit(blogPost)); diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostController.cs index ae679af55..7a6b7e571 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostController.cs @@ -38,9 +38,6 @@ namespace Orchard.Blogs.Controllers { //TODO: (erikpo) Should think about moving the slug parameters and get calls and null checks up into a model binder or action filter public ActionResult Item(string blogPath, string postSlug) { - if (!_services.Authorizer.Authorize(StandardPermissions.AccessFrontEnd, T("Couldn't view blog post"))) - return new HttpUnauthorizedResult(); - //TODO: (erikpo) Move looking up the current blog up into a modelbinder var blogPart = _blogService.Get(blogPath); if (blogPart == null) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs index fcc6881c0..3eca23437 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs @@ -1,32 +1,31 @@ using System.Linq; using Orchard.Blogs.Models; -using Orchard.Blogs.Routing; using Orchard.Blogs.Services; using Orchard.Blogs.ViewModels; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; +using Orchard.Core.Routable.Models; namespace Orchard.Blogs.Drivers { public class BlogArchivesPartDriver : ContentPartDriver { private readonly IBlogService _blogService; private readonly IBlogPostService _blogPostService; - private readonly IBlogPathConstraint _blogPathConstraint; + private readonly IContentManager _contentManager; public BlogArchivesPartDriver( IBlogService blogService, IBlogPostService blogPostService, - IBlogPathConstraint blogPathConstraint) { + IContentManager contentManager) { _blogService = blogService; _blogPostService = blogPostService; - _blogPathConstraint = blogPathConstraint; + _contentManager = contentManager; } protected override DriverResult Display(BlogArchivesPart part, string displayType, dynamic shapeHelper) { return ContentShape("Parts_Blogs_BlogArchives", () => { - var path = _blogPathConstraint.FindPath(part.ForBlog); - BlogPart blog = _blogService.Get(path); + BlogPart blog = GetBlogFromSlug(part.ForBlog); if (blog == null) return null; @@ -37,7 +36,7 @@ namespace Orchard.Blogs.Drivers { protected override DriverResult Editor(BlogArchivesPart part, dynamic shapeHelper) { var viewModel = new BlogArchivesViewModel { - Path = part.ForBlog, + Slug = part.ForBlog, Blogs = _blogService.Get().ToList().OrderBy(b => b.Name) }; @@ -48,7 +47,7 @@ namespace Orchard.Blogs.Drivers { protected override DriverResult Editor(BlogArchivesPart part, IUpdateModel updater, dynamic shapeHelper) { var viewModel = new BlogArchivesViewModel(); if (updater.TryUpdateModel(viewModel, Prefix, null, null)) { - part.ForBlog = viewModel.Path; + part.ForBlog = viewModel.Slug; } return Editor(part, shapeHelper); @@ -64,5 +63,11 @@ namespace Orchard.Blogs.Drivers { protected override void Exporting(BlogArchivesPart part, ExportContentContext context) { context.Element(part.PartDefinition.Name).SetAttributeValue("BlogSlug", part.ForBlog); } + + private BlogPart GetBlogFromSlug(string slug) { + return _contentManager.Query() + .Join().Where(rr => rr.Slug == slug) + .List().FirstOrDefault(); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs index 1dec86e46..207e97472 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs @@ -8,25 +8,22 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; using Orchard.Core.Common.Models; +using Orchard.Core.Routable.Models; namespace Orchard.Blogs.Drivers { public class RecentBlogPostsPartDriver : ContentPartDriver { private readonly IBlogService _blogService; private readonly IContentManager _contentManager; - private readonly IBlogPathConstraint _blogPathConstraint; public RecentBlogPostsPartDriver( IBlogService blogService, - IContentManager contentManager, - IBlogPathConstraint blogPathConstraint) { + IContentManager contentManager) { _blogService = blogService; _contentManager = contentManager; - _blogPathConstraint = blogPathConstraint; } protected override DriverResult Display(RecentBlogPostsPart part, string displayType, dynamic shapeHelper) { - var path = _blogPathConstraint.FindPath(part.ForBlog); - BlogPart blog = _blogService.Get(path); + BlogPart blog = GetBlogFromSlug(part.ForBlog); if (blog == null) { return null; @@ -43,13 +40,13 @@ namespace Orchard.Blogs.Drivers { var blogPostList = shapeHelper.Parts_Blogs_BlogPost_List(ContentPart: part, ContentItems: list); - return ContentShape(shapeHelper.Parts_Blogs_RecentBlogPosts(ContentItem: part.ContentItem, ContentItems: blogPostList)); + return ContentShape(shapeHelper.Parts_Blogs_RecentBlogPosts(ContentItem: part.ContentItem, ContentItems: blogPostList, Blog: blog)); } protected override DriverResult Editor(RecentBlogPostsPart part, dynamic shapeHelper) { var viewModel = new RecentBlogPostsViewModel { Count = part.Count, - Path = part.ForBlog, + Slug = part.ForBlog, Blogs = _blogService.Get().ToList().OrderBy(b => b.Name) }; @@ -60,7 +57,7 @@ namespace Orchard.Blogs.Drivers { protected override DriverResult Editor(RecentBlogPostsPart part, IUpdateModel updater, dynamic shapeHelper) { var viewModel = new RecentBlogPostsViewModel(); if (updater.TryUpdateModel(viewModel, Prefix, null, null)) { - part.ForBlog = viewModel.Path; + part.ForBlog = viewModel.Slug; part.Count = viewModel.Count; } @@ -83,5 +80,11 @@ namespace Orchard.Blogs.Drivers { context.Element(part.PartDefinition.Name).SetAttributeValue("BlogSlug", part.ForBlog); context.Element(part.PartDefinition.Name).SetAttributeValue("Count", part.Count); } + + private BlogPart GetBlogFromSlug(string slug) { + return _contentManager.Query() + .Join().Where(rr => rr.Slug == slug) + .List().FirstOrDefault(); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs index 8025145ae..817eea466 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs @@ -47,7 +47,7 @@ namespace Orchard.Blogs { cfg => cfg .WithPart("BlogPostPart") .WithPart("CommonPart", p => p - .WithSetting("CommonTypePartSettings.ShowCreatedUtcEditor", "true")) + .WithSetting("DateEditorSettings.ShowDateEditor", "true")) .WithPart("PublishLaterPart") .WithPart("RoutePart") .WithPart("BodyPart") @@ -69,7 +69,7 @@ namespace Orchard.Blogs { .WithSetting("Stereotype", "Widget") ); - return 3; + return 4; } public int UpdateFrom1() { @@ -81,5 +81,10 @@ namespace Orchard.Blogs { ContentDefinitionManager.AlterTypeDefinition("Blog", cfg => cfg.WithPart("AdminMenuPart", p => p.WithSetting("AdminMenuPartTypeSettings.DefaultPosition", "2"))); return 3; } + + public int UpdateFrom3() { + ContentDefinitionManager.AlterTypeDefinition("BlogPost", cfg => cfg.WithPart("CommonPart", p => p.WithSetting("DateEditorSettings.ShowDateEditor", "true"))); + return 4; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPart.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPart.cs index 485cebe9e..e364c32e5 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPart.cs @@ -3,6 +3,7 @@ using Orchard.ContentManagement; namespace Orchard.Blogs.Models { public class RecentBlogPostsPart : ContentPart { + public string ForBlog { get { return Record.BlogSlug; } set { Record.BlogSlug = value; } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPartRecord.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPartRecord.cs index 0d892792a..43881a8f0 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPartRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Models/RecentBlogPostsPartRecord.cs @@ -2,6 +2,10 @@ namespace Orchard.Blogs.Models { public class RecentBlogPostsPartRecord : ContentPartRecord { + public RecentBlogPostsPartRecord() { + Count = 5; + } + public virtual string BlogSlug { get; set; } public virtual int Count { get; set; } } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt index 605756f5c..edd504b9c 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Orchard Blogs module is implementing basic blogging features. FeatureDescription: A simple web log. Dependencies: Shapes, Common, Routable, Feeds, Navigation, Orchard.Widgets, Orchard.jQuery, Orchard.PublishLater diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs index 53f862151..9aad1e1c8 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index 0cbeadf4f..832756bc3 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -18,6 +18,7 @@ using Orchard.Logging; using Orchard.Mvc.Extensions; using Orchard.Security; using Orchard.Blogs.Extensions; +using Orchard.Mvc.Html; namespace Orchard.Blogs.Services { [UsedImplicitly] @@ -321,7 +322,12 @@ namespace Orchard.Blogs.Services { BlogPostPart blogPostPart, UrlHelper urlHelper) { - var url = urlHelper.AbsoluteAction(() => urlHelper.BlogPost(blogPostPart)); + var url = urlHelper.AbsoluteAction(() => urlHelper.ItemDisplayUrl(blogPostPart)); + + if (blogPostPart.HasDraft()) { + url = urlHelper.AbsoluteAction("Preview", "Item", new { area = "Contents", id = blogPostPart.ContentItem.Id }); + } + var blogStruct = new XRpcStruct() .Set("postid", blogPostPart.Id) .Set("title", blogPostPart.Title) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/BlogArchivesViewModel.cs b/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/BlogArchivesViewModel.cs index cd04428fe..274661006 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/BlogArchivesViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/BlogArchivesViewModel.cs @@ -3,7 +3,7 @@ using Orchard.Blogs.Models; namespace Orchard.Blogs.ViewModels { public class BlogArchivesViewModel { - public string Path { get; set; } + public string Slug { get; set; } public IEnumerable Blogs { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/RecentBlogPostsViewModel.cs b/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/RecentBlogPostsViewModel.cs index d576554ab..4ff906191 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/RecentBlogPostsViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/ViewModels/RecentBlogPostsViewModel.cs @@ -4,7 +4,7 @@ using Orchard.Blogs.Models; namespace Orchard.Blogs.ViewModels { public class RecentBlogPostsViewModel { public int Count { get; set; } - public string Path { get; set; } + public string Slug { get; set; } public IEnumerable Blogs { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.BlogArchives.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.BlogArchives.cshtml index f7c4e96a4..64204dc39 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.BlogArchives.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.BlogArchives.cshtml @@ -6,10 +6,10 @@
        - @Html.LabelFor(m => m.Path, T("For Blog")) - @foreach(BlogPart blog in Model.Blogs) { - @Html.SelectOption(Model.Path, blog.As().Slug, blog.Name) + @Html.SelectOption(Model.Slug, blog.As().Slug, blog.Name) } @T("Select which blog you want to display the archives for") diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.RecentBlogPosts.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.RecentBlogPosts.cshtml index f54f2e36f..9bf740aff 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.RecentBlogPosts.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/EditorTemplates/Parts.Blogs.RecentBlogPosts.cshtml @@ -6,16 +6,17 @@
        - @Html.LabelFor(m => m.Path, T("For Blog")) - @foreach(BlogPart blog in Model.Blogs) { - @Html.SelectOption(Model.Path, blog.As().Path, blog.Name) + @Html.SelectOption(Model.Slug, blog.As().Slug, blog.Name) } @T("Select which blog you want to display the recent posts for")
        @Html.LabelFor(m => m.Count, T("Count")) - @Html.TextBoxFor(m => m.Count) + @Html.TextBoxFor(m => m.Count, new { @class = "text-small"}) + @T("Number of posts to display. Zero for all.")
        \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt index f80a065c7..8a4587799 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/CodeGenerationTemplates/ModuleCsProj.txt @@ -6,7 +6,7 @@ 9.0.30729 2.0 {$$ModuleProjectGuid$$} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + {fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties $$ModuleName$$ diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs index 466f370c9..b343e5ef2 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs @@ -210,6 +210,7 @@ namespace Orchard.CodeGeneration.Commands { string propertiesPath = modulePath + "Properties"; var content = new HashSet(); var folders = new HashSet(); + var contentNoDeploy = new HashSet(); foreach(var folder in _moduleDirectories) { Directory.CreateDirectory(modulePath + folder); @@ -226,6 +227,8 @@ namespace Orchard.CodeGeneration.Commands { content.Add(modulePath + "Scripts\\Web.config"); File.WriteAllText(modulePath + "Styles\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt")); content.Add(modulePath + "Styles\\Web.config"); + File.WriteAllText(modulePath + "CodeTemplates\\AddController\\Controller.tt", File.ReadAllText(_codeGenTemplatePath + "Controller.tt.")); + contentNoDeploy.Add(modulePath + "CodeTemplates\\AddController\\Controller.tt"); string templateText = File.ReadAllText(_codeGenTemplatePath + "ModuleAssemblyInfo.txt"); templateText = templateText.Replace("$$ModuleName$$", moduleName); @@ -238,7 +241,7 @@ namespace Orchard.CodeGeneration.Commands { File.WriteAllText(modulePath + "Module.txt", templateText); content.Add(modulePath + "Module.txt"); - var itemGroup = CreateProjectItemGroup(modulePath, content, folders); + var itemGroup = CreateProjectItemGroup(modulePath, content, folders, contentNoDeploy); File.WriteAllText(modulePath + moduleName + ".csproj", CreateCsProject(moduleName, projectGuid, itemGroup)); } @@ -321,7 +324,7 @@ namespace Orchard.CodeGeneration.Commands { // create new csproj for the theme if (projectGuid != null) { - var itemGroup = CreateProjectItemGroup(themePath, createdFiles, createdFolders); + var itemGroup = CreateProjectItemGroup(themePath, createdFiles, createdFolders, null); string projectText = CreateCsProject(themeName, projectGuid, itemGroup); File.WriteAllText(themePath + "\\" + themeName + ".csproj", projectText); } @@ -329,7 +332,7 @@ namespace Orchard.CodeGeneration.Commands { if (includeInSolution) { if (projectGuid == null) { // include in solution but dont create a project: just add the references to Orchard.Themes project - var itemGroup = CreateProjectItemGroup(HostingEnvironment.MapPath("~/Themes/"), createdFiles, createdFolders); + var itemGroup = CreateProjectItemGroup(HostingEnvironment.MapPath("~/Themes/"), createdFiles, createdFolders, null); AddFilesToOrchardThemesProject(output, itemGroup); TouchSolution(output); } @@ -356,7 +359,8 @@ namespace Orchard.CodeGeneration.Commands { } } - private static string CreateProjectItemGroup(string relativeFromPath, HashSet content, HashSet folders) { + private static string CreateProjectItemGroup(string relativeFromPath, HashSet content, HashSet folders, HashSet contentNoDeploy) + { var contentInclude = ""; if (relativeFromPath != null && !relativeFromPath.EndsWith("\\", StringComparison.OrdinalIgnoreCase)) { relativeFromPath += "\\"; @@ -374,6 +378,10 @@ namespace Orchard.CodeGeneration.Commands { contentInclude += "\r\n" + string.Join("\r\n", from folder in folders select " "); } + if (contentNoDeploy != null && contentNoDeploy.Count > 0) { + contentInclude += "\r\n" + string.Join("\r\n", from file in contentNoDeploy + select " "); + } return string.Format(CultureInfo.InvariantCulture, "\r\n{0}\r\n \r\n ", contentInclude); } diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt index 36620298f..e9f5aeab6 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Tools to create Orchard components. FeatureDescription: Tools to create Orchard components. Category: Developer diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj index b490060bf..dfdc42f55 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Orchard.CodeGeneration.csproj @@ -14,6 +14,7 @@ Orchard.CodeGeneration v4.0 false + false true diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs index eca7425f7..fed45a04a 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Annotations/CommentValidationAttributes.cs b/src/Orchard.Web/Modules/Orchard.Comments/Annotations/CommentValidationAttributes.cs deleted file mode 100644 index 551afb931..000000000 --- a/src/Orchard.Web/Modules/Orchard.Comments/Annotations/CommentValidationAttributes.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Orchard.Localization; - -namespace Orchard.Comments.Annotations { - public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute { - public RequiredAttribute() { - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - public override string FormatErrorMessage(string name) { - return T("You must provide a {0} in order to comment.", name).Text; - } - } - - public class CommentRequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute { - public CommentRequiredAttribute() { - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - public override string FormatErrorMessage(string name) { - return T("You must provide a Comment.", name).Text; - } - } - - public class RegularExpressionAttribute : System.ComponentModel.DataAnnotations.RegularExpressionAttribute { - public RegularExpressionAttribute(string pattern) : base(pattern) { - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - public override string FormatErrorMessage(string name) { - return T("The {0} is not valid.", name).Text; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt index 3150295f5..87f8c3399 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt @@ -2,9 +2,17 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The comments system implemented by this module can be applied to arbitrary Orchard content types, such as blogs and pages. It includes comment validation and spam protection through the Akismet service. -FeatureDescription: Standard content item comments. -Dependencies: Settings -Category: Social +Features: + Orchard.Comments: + Name: Comments + Description: Standard content item comments. + Dependencies: Settings + Category: Social + Orchard.Comments.Rules: + Name: Comments Rules + Description: Rules for the Comments modules + Category: Rules + Dependencies: Orchard.Comments, Orchard.Rules \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj b/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj index 56ca5d211..4df3b95c1 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj +++ b/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj @@ -67,8 +67,9 @@ - + + diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs index 63ca324f3..5622f31eb 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] -[assembly: SecurityTransparent] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] +[assembly:SecurityTransparent] \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsActions.cs b/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsActions.cs new file mode 100644 index 000000000..277ce08b5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsActions.cs @@ -0,0 +1,47 @@ +using System; +using Orchard.Comments.Models; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.ContentManagement; +using Orchard.Localization; + +namespace Orchard.Comments.Rules { + public interface IActionProvider : IEventHandler { + void Describe(dynamic describe); + } + + [OrchardFeature("Orchard.Comments.Rules")] + public class CommentsActions : IActionProvider { + private readonly IContentManager _contentManager; + + public CommentsActions(IContentManager contentManager) { + _contentManager = contentManager; + } + + public Localizer T { get; set; } + + public void Describe(dynamic describe) { + Func display = context => T("Close comments"); + + describe.For("Comments", T("Comments"), T("Comments")) + .Element("Close", T("Close Comments"), T("Closes comments on a content item."), (Func)Close, display, "ActionCloseComments"); + } + + /// + /// Closes the comments on the content represented by "ContentId" + /// + private bool Close(dynamic context) { + var contentId = Convert.ToInt32(context.Properties["ContentId"]); + var content = _contentManager.Get(contentId); + + if (content != null) { + var comments = content.As(); + if (comments != null) { + comments.CommentsActive = false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsForms.cs b/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsForms.cs new file mode 100644 index 000000000..3d186c9df --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Comments/Rules/CommentsForms.cs @@ -0,0 +1,36 @@ +using System; +using Orchard.DisplayManagement; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.Localization; + +namespace Orchard.Comments.Rules { + public interface IFormProvider : IEventHandler { + void Describe(dynamic context); + } + + [OrchardFeature("Orchard.Comments.Rules")] + public class CommentsForms : IFormProvider { + protected dynamic Shape { get; set; } + public Localizer T { get; set; } + + public CommentsForms(IShapeFactory shapeFactory) { + Shape = shapeFactory; + } + + public void Describe(dynamic context) { + + Func form = + shape => Shape.Form( + Id: "ActionCloseComments", + _Type: Shape.Textbox( + Id: "ContentId", Name: "ContentId", + Title: T("Content Item Id"), + Description: T("Content Item Id."), + Classes: new [] { "tokenized" }) + ); + + context.Form("ActionCloseComments", form); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/ViewModels/CommentsCreateViewModel.cs b/src/Orchard.Web/Modules/Orchard.Comments/ViewModels/CommentsCreateViewModel.cs index 558d85e4c..94408a78a 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/ViewModels/CommentsCreateViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/ViewModels/CommentsCreateViewModel.cs @@ -1,21 +1,22 @@ -using System.ComponentModel.DataAnnotations; -using Orchard.Comments.Annotations; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; namespace Orchard.Comments.ViewModels { public class CommentsCreateViewModel { - [Annotations.Required] + [Required] [StringLength(255)] public string Name { get; set; } - [Annotations.RegularExpression(@"^[^@\s]+@[^@\s]+$")] + [RegularExpression(@"^[^@\s]+@[^@\s]+$")] [StringLength(255)] public string Email { get; set; } [StringLength(245)] - [Annotations.RegularExpression(@"^(http(s)?://)?([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}[\S]+$")] + [DisplayName("Site")] + [RegularExpression(@"^(http(s)?://)?([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}[\S]+$")] public string SiteName { get; set; } - [CommentRequired] + [Required, DisplayName("Comment")] public string CommentText { get; set; } public int CommentedOn { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml index 74dd7f968..1c198ee97 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml @@ -97,7 +97,7 @@ @T("Approve")@T(" | ") } else { - @("Unapprove")@T(" | ") + @T("Unapprove")@T(" | ") } @T("Edit")@T(" | ") @T("Delete") diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Views/CommentMetadata.cshtml b/src/Orchard.Web/Modules/Orchard.Comments/Views/CommentMetadata.cshtml index 3fa1082f1..72cc6afa8 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Views/CommentMetadata.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Comments/Views/CommentMetadata.cshtml @@ -9,4 +9,4 @@ var comment = (Orchard.Comments.Models.CommentPart)Model.ContentPart; } -said \ No newline at end of file +@T("said") \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/AdminMenu.cs index 8f6f52e82..2010cae4c 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/AdminMenu.cs @@ -7,10 +7,13 @@ namespace Orchard.ContentTypes { public Localizer T { get; set; } public string MenuName { get { return "admin"; } } - public void GetNavigation(NavigationBuilder builder) { - + public void GetNavigation(NavigationBuilder builder) + { builder.Add(T("Content"), - menu => menu.Add(T("Content Types"), "3", item => item.Action("Index", "Admin", new { area = "Orchard.ContentTypes" }).LocalNav())); + menu => menu + .Add(T("Content Types"), "3", item => item.Action("Index", "Admin", new {area = "Orchard.ContentTypes"}).LocalNav()) + .Add(T("Content Parts"), "4", item => item.Action("ListParts", "Admin", new {area = "Orchard.ContentTypes"}).LocalNav())); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs index df8589a95..5fae06822 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs @@ -6,6 +6,7 @@ using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentTypes.Services; using Orchard.ContentTypes.ViewModels; +using Orchard.Core.Contents.Controllers; using Orchard.Core.Contents.Settings; using Orchard.Localization; using Orchard.UI.Notify; @@ -72,6 +73,10 @@ namespace Orchard.ContentTypes.Controllers { } var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName); + + // adds CommonPart by default + _contentDefinitionService.AddPartToType("CommonPart", viewModel.Name); + var typeViewModel = new EditTypeViewModel(contentTypeDefinition); @@ -97,6 +102,7 @@ namespace Orchard.ContentTypes.Controllers { } [HttpPost, ActionName("Edit")] + [FormValueRequired("submit.Save")] public ActionResult EditPOST(string id) { if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to edit a content type."))) return new HttpUnauthorizedResult(); @@ -121,7 +127,6 @@ namespace Orchard.ContentTypes.Controllers { if (!ModelState.IsValid) return View(typeViewModel); - _contentDefinitionService.AlterType(typeViewModel, this); if (!ModelState.IsValid) { @@ -131,7 +136,32 @@ namespace Orchard.ContentTypes.Controllers { Services.Notifier.Information(T("\"{0}\" settings have been saved.", typeViewModel.DisplayName)); - return RedirectToAction("Index"); + return RedirectToAction("List"); + } + + + [HttpPost, ActionName("Edit")] + [FormValueRequired("submit.Delete")] + public ActionResult Delete(string id) { + if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to delete a content type."))) + return new HttpUnauthorizedResult(); + + var typeViewModel = _contentDefinitionService.GetType(id); + + if (typeViewModel == null) + return HttpNotFound(); + + _contentDefinitionManager.DeleteTypeDefinition(id); + + // delete all content items (but keep versions) + var contentItems = Services.ContentManager.Query(id).List(); + foreach (var contentItem in contentItems) { + Services.ContentManager.Remove(contentItem); + } + + Services.Notifier.Information(T("\"{0}\" has been removed.", typeViewModel.DisplayName)); + + return RedirectToAction("List"); } public ActionResult AddPartsTo(string id) { @@ -273,6 +303,7 @@ namespace Orchard.ContentTypes.Controllers { } [HttpPost, ActionName("EditPart")] + [FormValueRequired("submit.Save")] public ActionResult EditPartPOST(string id) { if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to edit a content part."))) return new HttpUnauthorizedResult(); @@ -297,6 +328,24 @@ namespace Orchard.ContentTypes.Controllers { return RedirectToAction("ListParts"); } + [HttpPost, ActionName("EditPart")] + [FormValueRequired("submit.Delete")] + public ActionResult DeletePart(string id) + { + if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to delete a content part."))) + return new HttpUnauthorizedResult(); + + var partViewModel = _contentDefinitionService.GetPart(id); + + if (partViewModel == null) + return HttpNotFound(); + + _contentDefinitionManager.DeletePartDefinition(id); + Services.Notifier.Information(T("\"{0}\" has been removed.", partViewModel.DisplayName)); + + return RedirectToAction("ListParts"); + } + public ActionResult AddFieldTo(string id) { if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to edit a content part."))) return new HttpUnauthorizedResult(); diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt b/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt index 00b926087..e74addceb 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: ContentTypes modules enables the creation and alteration of content types not based on code. Dependencies: Contents Category: Content diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs index 59ad5f9ae..3a09dce5f 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.ContentTypes")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.ContentTypes")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/AddPartsTo.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/AddPartsTo.cshtml index 033e57d9e..ea9e82f00 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/AddPartsTo.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/AddPartsTo.cshtml @@ -3,7 +3,7 @@ Style.Require("ContentTypesAdmin"); Layout.Title = T("Add Parts To \"{0}\"", Model.Type.DisplayName).ToString(); } -@T("Choose the Parts to add to this Content Type. The Common part should be included in most types. It gives the items an owner as well as a creation, publication and last modification date stamps. In addition to the Common part, adding the Containable part makes it possible to add content items of this type to a List.") +@T("Choose the Parts to add to this Content Type. Adding the Containable part makes it possible to add content items of this type to a List.") @using (Html.BeginFormAntiForgeryPost()) { @Html.ValidationSummary()
        diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml index 8c496327d..b26d4ce0a 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml @@ -5,7 +5,6 @@ Layout.Title = T("Edit Content Type").ToString(); } - @using (Html.BeginFormAntiForgeryPost()) { // todo: come up with real itemtype definitions and locations for said definitions
        @@ -34,7 +33,8 @@ @Html.EditorFor(m => m.Parts, "TypeParts", "")
        - + +
        } diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPart.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPart.cshtml index d563df21d..470f6c49b 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPart.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPart.cshtml @@ -5,7 +5,6 @@ Layout.Title = T("Edit Part").ToString(); } - @using (Html.BeginFormAntiForgeryPost()) { @Html.ValidationSummary()
        @@ -23,7 +22,8 @@ @Html.EditorFor(m => m.Fields, "Fields", "")
        - + +
        } diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/List.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/List.cshtml index 5661070ea..bf80d408a 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/List.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/List.cshtml @@ -6,7 +6,6 @@
        @Html.ActionLink(T("Create new type").ToString(), "Create", new{Controller="Admin",Area="Orchard.ContentTypes"}, new { @class = "button primaryAction" }) - @Html.ActionLink(T("Content Parts").ToString(), "ListParts", new{Controller="Admin",Area="Orchard.ContentTypes"}, new { @class = "button" })
        @Html.UnorderedList( Model.Types, diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/ListParts.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/ListParts.cshtml index 5aceeceb9..dbe1df815 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/ListParts.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/ListParts.cshtml @@ -2,7 +2,6 @@ @{ Layout.Title = T("Content Parts").ToString(); } -
        @Html.ActionLink(T("Create new part").ToString(), "CreatePart", new{Controller="Admin",Area="Orchard.ContentTypes"}, new { @class = "button primaryAction" })
        diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/DisplayTemplates/EditPartViewModel.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/DisplayTemplates/EditPartViewModel.cshtml index e615b08a8..84c9319b2 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/DisplayTemplates/EditPartViewModel.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/DisplayTemplates/EditPartViewModel.cshtml @@ -4,6 +4,6 @@

        @Model.DisplayName

        \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt b/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt index 375c448d6..f7139a7a4 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Contains designer tools to ease the Themes development process FeatureName: Shape Tracing Category: Designer @@ -14,3 +14,8 @@ Features: Name: Url Alternates Category: Designer Description: Adds shape alternates for specific urls + WidgetAlternates: + Name: Widget Alternates + Category: Designer + Description: Adds shape alternates for content types stereotyped as widgets, allowing to customize shapes by widget and zone + Dependencies: Orchard.Widgets diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Orchard.DesignerTools.csproj b/src/Orchard.Web/Modules/Orchard.DesignerTools/Orchard.DesignerTools.csproj index 16a517238..2729f6263 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Orchard.DesignerTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Orchard.DesignerTools.csproj @@ -100,6 +100,10 @@ {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core + + {194D3CCC-1153-474D-8176-FDE8D7D0D0BD} + Orchard.Widgets + @@ -107,6 +111,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs index aa7a28179..011369c11 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -9,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("Orchard")] -[assembly: AssemblyCopyright("")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,5 +31,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] +[assembly: SecurityTransparent] \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/WidgetAlternatesFactory.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/WidgetAlternatesFactory.cs new file mode 100644 index 000000000..03c8f3afd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/WidgetAlternatesFactory.cs @@ -0,0 +1,34 @@ +using Orchard.DisplayManagement.Implementation; +using Orchard.Environment.Extensions; +using Orchard.ContentManagement; +using Orchard.Widgets.Models; + +namespace Orchard.DesignerTools.Services { + [OrchardFeature("WidgetAlternates")] + public class WidgetAlternatesFactory : ShapeDisplayEvents { + public override void Displaying(ShapeDisplayingContext context) { + context.ShapeMetadata.OnDisplaying(displayedContext => { + // We don't want the "Widget" content item itself, but the content item that consists of the Widget part (e.g. Parts.Blogs.RecentBlogPosts) + if (displayedContext.ShapeMetadata.Type != "Widget") { + ContentItem contentItem = displayedContext.Shape.ContentItem; + if (contentItem != null) { + // Is the contentItem a widget? (we could probably test for the stereotype setting, don't know if that is more efficient than selecting the WidgetPart) + var widgetPart = contentItem.As(); + if (widgetPart != null) { + var zoneName = widgetPart.Zone; + var shapeName = displayedContext.ShapeMetadata.Type; + var contentTypeName = contentItem.ContentType; + + // Add 2 alternates for flexible widget shape naming: + // [ShapeName]-[ZoneName].cshtml: (e.g. "Parts.Blogs.RecentBlogPosts-myZoneName.cshtml") + // [ContentTypeName]-[ZoneName].cshtml: (e.g. "RecentBlogPosts-myZoneName.cshtml") + displayedContext.ShapeMetadata.Alternates.Add(contentTypeName + "__" + zoneName); + displayedContext.ShapeMetadata.Alternates.Add(shapeName + "__" + zoneName); + } + } + } + }); + + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Email/Module.txt b/src/Orchard.Web/Modules/Orchard.Email/Module.txt index a5701b8d5..6b4b7eacc 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Email/Module.txt @@ -2,9 +2,17 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Email Messaging module adds Email sending functionalities. -FeatureDescription: Email Messaging services. -Category: Messaging -Dependencies: Orchard.Messaging +Features: + Orchard.Email: + Name: Email Messaging + FeatureDescription: Email Messaging services. + Category: Messaging + Dependencies: Orchard.Messaging + Orchard.Email.Rules: + Name: Email Rules + Description: Rules for the Email modules + Category: Rules + Dependencies: Orchard.Email, Orchard.Rules \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj b/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj index eaa3b524f..d72d77bfc 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj +++ b/src/Orchard.Web/Modules/Orchard.Email/Orchard.Email.csproj @@ -18,6 +18,7 @@ 3.5 + false true @@ -54,6 +55,8 @@ + + diff --git a/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs index 71636bed6..6ee5eaec7 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Email/Rules/MailActions.cs b/src/Orchard.Web/Modules/Orchard.Email/Rules/MailActions.cs new file mode 100644 index 000000000..28ea19360 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Email/Rules/MailActions.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using Orchard.ContentManagement.Records; +using Orchard.Core.Common.Models; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.Messaging.Events; +using Orchard.Messaging.Models; +using Orchard.Messaging.Services; +using Orchard.ContentManagement; +using Orchard.Localization; +using Orchard.Security; + +namespace Orchard.Email.Rules { + + public interface IActionProvider : IEventHandler { + void Describe(dynamic describe); + } + + [OrchardFeature("Orchard.Email.Rules")] + public class MailActions : IActionProvider { + private readonly IMessageManager _messageManager; + private readonly IOrchardServices _orchardServices; + private readonly IMembershipService _membershipService; + public const string MessageType = "ActionEmail"; + + public MailActions( + IMessageManager messageManager, + IOrchardServices orchardServices, + IMembershipService membershipService) { + _messageManager = messageManager; + _orchardServices = orchardServices; + _membershipService = membershipService; + } + + public Localizer T { get; set; } + + public void Describe(dynamic describe) { + Func display = context => T("Send an e-mail"); + + describe.For("Messaging", T("Messaging"), T("Messages")) + .Element("SendEmail", T("Send e-mail"), T("Sends an e-mail to a specific user."), (Func)Send, display, "ActionEmail"); + } + + private bool Send(dynamic context) { + var recipient = context.Properties["Recipient"]; + ContentItemRecord recipientRecord = null; + + if (recipient == "owner") { + var content = context.Tokens["Content"] as IContent; + if (content.Has()) { + recipientRecord = content.As().Owner.ContentItem.Record; + } + } + + if (recipient == "author") { + var user = _orchardServices.WorkContext.CurrentUser; + + // can be null if user is anonymous + if (user != null && String.IsNullOrWhiteSpace(user.Email)) { + recipientRecord = user.ContentItem.Record; + } + } + + if (recipient == "admin") { + var username = _orchardServices.WorkContext.CurrentSite.SuperUser; + var user = _membershipService.GetUser(username); + + // can be null if user is no super user is defined + if (user != null && !String.IsNullOrWhiteSpace(user.Email)) { + recipientRecord = user.ContentItem.Record; + } + } + + if (recipientRecord == null) { + return true; + } + + var properties = new Dictionary(context.Properties); + + _messageManager.Send(recipientRecord, MessageType, "email", properties); + + return true; + } + } + + public class MailActionsHandler : IMessageEventHandler { + private readonly IContentManager _contentManager; + + public MailActionsHandler(IContentManager contentManager) { + _contentManager = contentManager; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + public void Sending(MessageContext context) { + if (context.MessagePrepared) + return; + + var contentItem = _contentManager.Get(context.Recipient.Id); + if (contentItem == null) + return; + + var recipient = contentItem.As(); + if (recipient == null) + return; + + switch (context.Type) { + case MailActions.MessageType: + context.MailMessage.Subject = context.Properties["Subject"]; + context.MailMessage.Body = context.Properties["Body"]; + FormatEmailBody(context); + context.MessagePrepared = true; + break; + } + } + + private static void FormatEmailBody(MessageContext context) { + context.MailMessage.Body = "

        " + context.MailMessage.Body; + context.MailMessage.Body += "

        "; + } + + public void Sent(MessageContext context) { + } + } + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Email/Rules/MailForms.cs b/src/Orchard.Web/Modules/Orchard.Email/Rules/MailForms.cs new file mode 100644 index 000000000..f19d21781 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Email/Rules/MailForms.cs @@ -0,0 +1,73 @@ +using System; +using System.Web.Mvc; +using Orchard.DisplayManagement; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.Localization; + +namespace Orchard.Email.Rules { + public interface IFormProvider : IEventHandler { + void Describe(dynamic context); + } + + [OrchardFeature("Orchard.Email.Rules")] + public class MailForms : IFormProvider { + protected dynamic Shape { get; set; } + public Localizer T { get; set; } + + public MailForms(IShapeFactory shapeFactory) { + Shape = shapeFactory; + } + + public void Describe(dynamic context) { + Func form = + shape => Shape.Form( + Id: "ActionEmail", + _Type: Shape.SelectList( + Id: "Recipient", Name: "Recipient", + Title: T("Send to"), + Description: T("Select who should be the recipient of this e-mail.")) + .Add(new SelectListItem { Value = "owner", Text = T("Owner").Text }) + .Add(new SelectListItem { Value = "author", Text = T("Author").Text }) + .Add(new SelectListItem { Value = "admin", Text = T("Site Admin").Text }), + _Subject: Shape.Textbox( + Id: "Subject", Name: "Subject", + Title: T("Subject"), + Description: T("The subject of the e-mail."), + Classes: new[] { "large", "text", "tokenized" }), + _Message: Shape.Textarea( + Id: "Body", Name: "Body", + Title: T("Body"), + Description: T("The body of the e-mail."), + Classes: new[] { "tokenized" } + ) + ); + + context.Form("ActionEmail", form); + } + } + + public interface IFormHandler : IEventHandler { + void Validating(dynamic context); + } + + public class MailFormsValitator : IFormHandler { + public Localizer T { get; set; } + + public void Validating(dynamic context) { + if (context.FormName == "ActionEmail") { + if (context.ValueProdiver.GetValue("Recipient").AttemptedValue == String.Empty) { + context.ModelState.AddModelError("Recipient", T("You must select at least one recipient").Text); + } + + if (context.ValueProdiver.GetValue("Subject").AttemptedValue == String.Empty) { + context.ModelState.AddModelError("Subject", T("You must provide a Subject").Text); + } + + if (context.ValueProdiver.GetValue("Body").AttemptedValue == String.Empty) { + context.ModelState.AddModelError("Body", T("You must provide a Body").Text); + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs b/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs index df0e7f213..a0adcb6b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Services/MissingSettingsBanner.cs @@ -1,27 +1,37 @@ using System.Collections.Generic; +using System.Web.Mvc; using Orchard.ContentManagement; -using Orchard.Localization; using Orchard.Email.Models; +using Orchard.Localization; using Orchard.UI.Admin.Notification; using Orchard.UI.Notify; -namespace Orchard.Email.Services { - public class MissingSettingsBanner: INotificationProvider { +namespace Orchard.Email.Services +{ + public class MissingSettingsBanner : INotificationProvider + { private readonly IOrchardServices _orchardServices; + private readonly WorkContext _workContext; - public MissingSettingsBanner(IOrchardServices orchardServices) { + public MissingSettingsBanner(IOrchardServices orchardServices, WorkContext workContext) + { _orchardServices = orchardServices; + _workContext = workContext; T = NullLocalizer.Instance; } public Localizer T { get; set; } - public IEnumerable GetNotifications() { + public IEnumerable GetNotifications() + { var smtpSettings = _orchardServices.WorkContext.CurrentSite.As(); - if ( smtpSettings == null || !smtpSettings.IsValid() ) { - yield return new NotifyEntry { Message = T("The SMTP settings needs to be configured." ), Type = NotifyType.Warning}; + if (smtpSettings == null || !smtpSettings.IsValid()) + { + var urlHelper = new UrlHelper(_workContext.HttpContext.Request.RequestContext); + var url = urlHelper.Action("Email", "Admin", new { Area = "Settings" }); + yield return new NotifyEntry { Message = T("The SMTP settings needs to be configured.", url), Type = NotifyType.Warning }; } } } diff --git a/src/Orchard.Web/Modules/Orchard.Experimental/Module.txt b/src/Orchard.Web/Modules/Orchard.Experimental/Module.txt index 84f07b9b0..756659653 100644 --- a/src/Orchard.Web/Modules/Orchard.Experimental/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Experimental/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: An assortment of debugging tools. Category: Developer Features: diff --git a/src/Orchard.Web/Modules/Orchard.Experimental/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Experimental/Properties/AssemblyInfo.cs index 8b3962d2c..ed8bbd4d9 100644 --- a/src/Orchard.Web/Modules/Orchard.Experimental/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Experimental/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs index d1c70e16e..d53fe45bc 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Controllers/AdminController.cs @@ -53,7 +53,7 @@ namespace Orchard.ImportExport.Controllers { public ActionResult Export() { var viewModel = new ExportViewModel { ContentTypes = new List() }; - foreach (var contentType in _contentDefinitionManager.ListTypeDefinitions()) { + foreach (var contentType in _contentDefinitionManager.ListTypeDefinitions().OrderBy(c => c.Name)) { viewModel.ContentTypes.Add(new ContentTypeEntry { ContentTypeName = contentType.Name }); } return View(viewModel); diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt b/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt index ab0ffe066..4f83017d3 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt @@ -3,8 +3,8 @@ Path: ImportExport AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Provides content item data import and export capability. FeatureDescription: Imports and exports content item data Category: Content diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs index f0a7438ae..c777c4600 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.ImportExport")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.ImportExport")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml b/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml index 15cfde716..f9b9b1e02 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Views/Admin/Export.cshtml @@ -9,10 +9,11 @@
          @{var contentTypeIndex = 0;} @foreach (var contentTypeEntry in Model.ContentTypes) { -
        1. - - -
        2. +
        3. + + + +
        4. contentTypeIndex = contentTypeIndex + 1; }
        diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt b/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt index 68fd71279..7aa131ed7 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Indexing module enables the site to be indexed. The index generated by this module can then be used by the search module to provide an integrated full-text search experience to a web site. FeatureDescription: Indexing infrastructure. Requires an index implementation like the Lucene module. Category: Search diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs index 7e300581c..d6f9bfc7f 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Indexing")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Indexing")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs index e0cf28360..9d910cd1e 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs @@ -178,7 +178,7 @@ namespace Orchard.Indexing.Services { .OrderBy(x => x.Id) .Take(ContentItemsPerLoop) .GroupBy(x => x.ContentItemRecord.Id) - .Select(group => new {TaskId = group.Max(task => task.Id), Id = group.Key, ContentItem = _contentManager.Get(group.Key, VersionOptions.Published)}) + .Select(group => new {TaskId = group.Max(task => task.Id), Delete = group.Last().Action == IndexingTaskRecord.Delete, Id = group.Key, ContentItem = _contentManager.Get(group.Key, VersionOptions.Published)}) .OrderBy(x => x.TaskId) .ToArray(); @@ -187,7 +187,7 @@ namespace Orchard.Indexing.Services { // item.ContentItem can be null if the content item has been deleted IDocumentIndex documentIndex = ExtractDocumentIndex(item.ContentItem); - if (documentIndex == null) { + if (documentIndex == null || item.Delete) { deleteFromIndex.Add(item.Id); } else if (documentIndex.IsDirty) { diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs index 6d63d7c22..b269d0f5d 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs @@ -1,7 +1,6 @@ using System; -using System.Globalization; -using System.Linq; using System.Collections.Generic; +using System.Linq; using System.Web.Mvc; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; @@ -11,24 +10,19 @@ using Orchard.Core.Containers.Models; using Orchard.Core.Contents; using Orchard.Core.Contents.Controllers; using Orchard.Core.Contents.Settings; -using Orchard.Core.Routable.Models; -using Orchard.Data; using Orchard.DisplayManagement; -using Orchard.DisplayManagement.Shapes; using Orchard.Lists.ViewModels; using Orchard.Localization; -using Orchard; using Orchard.Logging; using Orchard.Mvc.Extensions; using Orchard.Settings; using Orchard.UI.Navigation; using Orchard.UI.Notify; -namespace Lists.Controllers { +namespace Orchard.Lists.Controllers { public class AdminController : Controller { private readonly IContentManager _contentManager; private readonly IContentDefinitionManager _contentDefinitionManager; - private readonly ITransactionManager _transactionManager; private readonly ISiteService _siteService; public IOrchardServices Services { get; set; } @@ -37,13 +31,12 @@ namespace Lists.Controllers { IOrchardServices orchardServices, IContentManager contentManager, IContentDefinitionManager contentDefinitionManager, - ITransactionManager transactionManager, ISiteService siteService, IShapeFactory shapeFactory) { + Services = orchardServices; _contentManager = contentManager; _contentDefinitionManager = contentDefinitionManager; - _transactionManager = transactionManager; _siteService = siteService; T = NullLocalizer.Instance; Logger = NullLogger.Instance; @@ -118,8 +111,14 @@ namespace Lists.Controllers { } private IContentQuery GetListContentItemQuery(int containerId, string contentType, ContentsOrder orderBy) { - var query = _contentManager.Query(VersionOptions.Latest, GetContainableTypes().Select(ctd => ctd.Name).ToArray()); + List containableTypes = GetContainableTypes().Select(ctd => ctd.Name).ToList(); + if (containableTypes.Count == 0) { + // Force the name to be matched against empty and return no items in the query + containableTypes.Add(string.Empty); + } + var query = _contentManager.Query(VersionOptions.Latest, containableTypes.ToArray()); + if (!string.IsNullOrEmpty(contentType)) { var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(contentType); if (contentTypeDefinition == null) { @@ -131,7 +130,6 @@ namespace Lists.Controllers { query = containerId == 0 ? query.Join().Where(cr => cr.Container == null) : query.Join().Where(cr => cr.Container.Id == containerId); - switch (orderBy) { case ContentsOrder.Modified: query = query.OrderByDescending(cr => cr.ModifiedUtc); @@ -143,6 +141,7 @@ namespace Lists.Controllers { query = query.OrderByDescending(cr => cr.CreatedUtc); break; } + return query; } diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Module.txt b/src/Orchard.Web/Modules/Orchard.Lists/Module.txt index 56d6e84d5..fee1d9aef 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Lists/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Introduces a preconfigured container-enabled content type. FeatureDescription: A basic container-enabled content type. Dependencies: Contents, Containers, Navigation diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs index 2e4ba11b0..89743f0fa 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Security; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("Orchard")] -[assembly: AssemblyCopyright("Copyright � Outercurve Foundation 2009")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Models/LocalizationPart.cs b/src/Orchard.Web/Modules/Orchard.Localization/Models/LocalizationPart.cs index d35e37189..6498fdcd2 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Models/LocalizationPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Models/LocalizationPart.cs @@ -1,9 +1,10 @@ using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.Utilities; using Orchard.Localization.Records; namespace Orchard.Localization.Models { - public sealed class LocalizationPart : ContentPart { + public sealed class LocalizationPart : ContentPart, ILocalizableAspect { private readonly LazyField _culture = new LazyField(); private readonly LazyField _masterContentItem = new LazyField(); @@ -25,5 +26,9 @@ namespace Orchard.Localization.Models { return Record.MasterContentItemId != 0; } } + + string ILocalizableAspect.Culture { + get { return Culture == null ? null : Culture.Culture; } + } } } diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Module.txt b/src/Orchard.Web/Modules/Orchard.Localization/Module.txt index 2d8f50c9d..ca783831b 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Localization/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The localization module enables the localization of content items. FeatureDescription: Localize content items. Dependencies: Settings diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs index ee5a2c1ab..ee9f32a85 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Localization")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Localization")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,6 +31,6 @@ using System.Security; // 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.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml index 5325ed79a..b4e9126e9 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml @@ -1,7 +1,7 @@ @model Orchard.Localization.ViewModels.EditLocalizationViewModel -@if (Model.ContentItem.ContentItem.Id > 0 && Model.SelectedCulture != null && Model.ContentLocalizations.Localizations.Count() > 0) { -Style.Require("LocalizationAdmin");
        +@if (Model.ContentItem.ContentItem.Id > 0 && Model.SelectedCulture != null && Model.ContentLocalizations.Localizations.Count() > 0) { + Style.Require("LocalizationAdmin");
        @T("This is the {0} variation of {1}.", @@ -9,7 +9,7 @@ Style.Require("LocalizationAdmin"); Html.ItemEditLink(Model.MasterContentItem ?? Model.ContentItem))
        @Html.Hidden("SelectedCulture", Model.SelectedCulture)
        - @if (Model.ContentLocalizations.Localizations.Count() > 0) { + if (Model.ContentLocalizations.Localizations.Count() > 0) {
        @T("Other translations:")
        @@ -17,4 +17,6 @@ Style.Require("LocalizationAdmin");
        } -
        } \ No newline at end of file +} +
        @Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.ContentItem.Id }, null)
        +
        diff --git a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs index e3d7ad359..ef4087ea5 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs @@ -41,6 +41,8 @@ namespace Orchard.Media.Controllers { foreach (string key in input.Keys) { if (key.StartsWith("Checkbox.") && input[key] == "true") { string folderName = key.Substring("Checkbox.".Length); + if (!Services.Authorizer.Authorize(Permissions.ManageMedia, T("Couldn't delete media folder"))) + return new HttpUnauthorizedResult(); _mediaService.DeleteFolder(folderName); } } diff --git a/src/Orchard.Web/Modules/Orchard.Media/Module.txt b/src/Orchard.Web/Modules/Orchard.Media/Module.txt index e0e10e153..116ed316a 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Media/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The media module offer basic media management features. It currently only supports image files. Storage goes into the current Orchard file system, which can be the server's physical file system or Azure blob storage. FeatureDescription: File system based media upload, storage and management. Category: Media diff --git a/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs index f171beb8a..b956d23ce 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs index 2d71b1c4f..4ba79adaa 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Services/XmlRpcHandler.cs @@ -1,9 +1,13 @@ using System; using System.IO; +using System.Web.Mvc; +using System.Web.Routing; using System.Xml.Linq; using JetBrains.Annotations; using Orchard.Core.XmlRpc; using Orchard.Core.XmlRpc.Models; +using Orchard.Mvc.Extensions; +using Orchard.Utility.Extensions; using Orchard.Security; namespace Orchard.Media.Services { @@ -12,14 +16,17 @@ namespace Orchard.Media.Services { private readonly IMembershipService _membershipService; private readonly IAuthorizationService _authorizationService; private readonly IMediaService _mediaService; + private readonly RouteCollection _routeCollection; public XmlRpcHandler( IMembershipService membershipService, IAuthorizationService authorizationService, - IMediaService mediaService) { + IMediaService mediaService, + RouteCollection routeCollection) { _membershipService = membershipService; _authorizationService = authorizationService; _mediaService = mediaService; + _routeCollection = routeCollection; } public void SetCapabilities(XElement options) { @@ -28,11 +35,14 @@ namespace Orchard.Media.Services { } public void Process(XmlRpcContext context) { + var urlHelper = new UrlHelper(context.ControllerContext.RequestContext, _routeCollection); + if (context.Request.MethodName == "metaWeblog.newMediaObject") { var result = MetaWeblogNewMediaObject( Convert.ToString(context.Request.Params[1].Value), Convert.ToString(context.Request.Params[2].Value), - (XRpcStruct)context.Request.Params[3].Value); + (XRpcStruct)context.Request.Params[3].Value, + urlHelper); context.Response = new XRpcMethodResponse().Add(result); } } @@ -40,7 +50,8 @@ namespace Orchard.Media.Services { private XRpcStruct MetaWeblogNewMediaObject( string userName, string password, - XRpcStruct file) { + XRpcStruct file, + UrlHelper url) { var user = _membershipService.ValidateUser(userName, password); if (!_authorizationService.TryCheckAccess(Permissions.ManageMedia, user, null)) { @@ -52,7 +63,7 @@ namespace Orchard.Media.Services { var bits = file.Optional("bits"); string publicUrl = _mediaService.UploadMediaFile(Path.GetDirectoryName(name), Path.GetFileName(name), bits, true); - return new XRpcStruct().Set("url", publicUrl); + return new XRpcStruct().Set("url", url.MakeAbsolute(publicUrl)); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.MediaPicker/Controllers/AdminController.cs index 873d5a73b..09ee2d0a9 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Controllers/AdminController.cs @@ -37,15 +37,15 @@ namespace Orchard.MediaPicker.Controllers { [HttpPost] public JsonResult CreateFolder(string path, string folderName) { if (!Services.Authorizer.Authorize(Permissions.ManageMedia)) { - return Json(T("Couldn't create media folder").ToString()); + return Json(new { Success = false, Message = T("Couldn't create media folder").ToString() }); } try { _mediaService.CreateFolder(HttpUtility.UrlDecode(path), folderName); - return Json(true); + return Json(new { Success = true, Message = "" }); } catch (Exception exception) { - return Json(T("Creating Folder failed: {0}", exception.Message).ToString()); + return Json(new { Success = false, Message = T("Creating Folder failed: {0}", exception.Message).ToString()} ); } } } diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Module.txt b/src/Orchard.Web/Modules/Orchard.MediaPicker/Module.txt index 19d45a044..dd5061735 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Module.txt @@ -3,8 +3,8 @@ Path: MediaPicker AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Description for the module Dependencies: Orchard.Media, Orchard.jQuery FeatureDescription: UI for browsing for, uploading, or selecting an image for an HTML editor. diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MediaPicker/Properties/AssemblyInfo.cs index d2acd811d..3c3452eb1 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Properties/AssemblyInfo.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -9,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("Orchard")] -[assembly: AssemblyCopyright("")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,5 +31,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] +[assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Scripts/MediaBrowser.js b/src/Orchard.Web/Modules/Orchard.MediaPicker/Scripts/MediaBrowser.js index a9256413e..997eaf089 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Scripts/MediaBrowser.js +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Scripts/MediaBrowser.js @@ -45,17 +45,25 @@ }); $("#createFolder").live("click", function () { + if ($(this).hasClass("disabled")) return; $.post("MediaPicker/CreateFolder", { path: query("mediaPath") || "", folderName: $("#folderName").val(), __RequestVerificationToken: $("#__requesttoken").val() }, function (response) { - if (typeof response === "string") { - alert(response); - } - else { + if (response.Success) { location.reload(true); - } + } else if (response.Success === false) { + alert(response.Message); + } else if (response.indexOf($.mediaPicker.logonUrl) !== -1) { + // A redirection due to expired authorization + alert($.mediaPicker.accessDeniedMsg); + } else alert($.mediaPicker.cannotPerformMsg); }); }); + $("#folderName").live("propertychange keyup input paste", function () { + var empty = ($("#folderName").val() == ""); + $("#createFolder").attr("disabled", empty).toggleClass("disabled", empty); + }); + $(function () { $("#tabs").tabs({ selected: parseInt(query("tab", location.hash)) || 0, @@ -81,7 +89,7 @@ var preselect = query("select", location.hash); if (preselect) { - $("img[data-filename=" + preselect + "]").closest(".media-item").trigger("click"); + $("img[data-filename='" + preselect + "']").closest(".media-item").trigger("click"); } // edit mode has slightly different wording @@ -101,8 +109,15 @@ }); } - var data = window.opener.jQuery[query("callback")].data, + try { + var data = window.opener.jQuery[query("callback")].data, img = data ? data.img : null; + } + catch (ex) { + alert($.mediaPicker.cannotPerformMsg); + window.close(); + } + if (img) { for (var name in img) { $("#img-" + name).val(img[name]); @@ -140,7 +155,12 @@ height: $(prefix + "height").val() }; img.html = getImageHtml(img); - window.opener.jQuery[query("callback")]({ img: img }); + try { + window.opener.jQuery[query("callback")]({ img: img }); + } + catch (ex) { + alert($.mediaPicker.cannotPerformMsg); + } window.close(); } @@ -274,6 +294,9 @@ else if (result && result.error) { alert(result.error); } + else if (frame.location.pathname.match("AccessDenied")) { + alert($.mediaPicker.accessDeniedMsg); + } else { var somethingPotentiallyHorrible = ""; try { diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Index.cshtml index 8320e9723..76e18a79c 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Index.cshtml @@ -29,6 +29,12 @@ + +
        • @T("Insert/Upload Image")
        • diff --git a/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Tab_Gallery.cshtml b/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Tab_Gallery.cshtml index 75f0c505a..da106ec43 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Tab_Gallery.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaPicker/Views/Admin/Tab_Gallery.cshtml @@ -28,7 +28,7 @@
          - +
        diff --git a/src/Orchard.Web/Modules/Orchard.Messaging/Module.txt b/src/Orchard.Web/Modules/Orchard.Messaging/Module.txt index aba5ee597..68d1078b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Messaging/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Messaging/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Messaging module adds messaging functionalities. FeatureDescription: Messaging services. Category: Messaging diff --git a/src/Orchard.Web/Modules/Orchard.Messaging/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Messaging/Properties/AssemblyInfo.cs index c2860d6b3..898932a20 100644 --- a/src/Orchard.Web/Modules/Orchard.Messaging/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Messaging/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Messaging")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Messaging")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,6 +31,6 @@ using System.Security; // 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.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Migrations/Module.txt b/src/Orchard.Web/Modules/Orchard.Migrations/Module.txt index c0242b5e0..5529e654e 100644 --- a/src/Orchard.Web/Modules/Orchard.Migrations/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Migrations/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Data migration commands. FeatureDescription: Data migration commands. Category: Developer diff --git a/src/Orchard.Web/Modules/Orchard.Migrations/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Migrations/Properties/AssemblyInfo.cs index e9afcef1c..9353300be 100644 --- a/src/Orchard.Web/Modules/Orchard.Migrations/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Migrations/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Data/Migration/DataMigrationNotificationProvider.cs b/src/Orchard.Web/Modules/Orchard.Modules/Data/Migration/DataMigrationNotificationProvider.cs index 72d6cf1e9..a59beb7b7 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Data/Migration/DataMigrationNotificationProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Data/Migration/DataMigrationNotificationProvider.cs @@ -10,6 +10,11 @@ using Orchard.UI.Admin.Notification; using Orchard.UI.Notify; namespace Orchard.Modules.Data.Migration { + /// + /// This implementation overrides the Core notification provider. It has been replaced + /// because some links to the features had to be displayed, links that are pointing to + /// this module. So in case the module is removed, the notifications would still be displayed. + /// [OrchardSuppressDependency("Orchard.Data.Migration.DataMigrationNotificationProvider")] public class DataMigrationNotificationProvider : INotificationProvider { private readonly IDataMigrationManager _dataMigrationManager; diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt index cfe9749c0..94bac9976 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The Modules module enables the administrator of the site to manage the installed modules as well as activate and de-activate features. FeatureDescription: Standard module and feature management. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Modules/Properties/AssemblyInfo.cs index 461d394ca..565e9a884 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml index 9fc0085bc..1dafa7c77 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml @@ -26,8 +26,7 @@ categoryClassName += " last"; } - //temporarily "disable" actions on core features - bool showActions; + bool showEnable, showDisable;
      • @categoryName

          @{ @@ -53,7 +52,8 @@ select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name); var missingDependencies = feature.Descriptor.Dependencies .Where(d => !Model.Features.Any(f => f.Descriptor.Id == d)); - showActions = categoryName.ToString() != "Core" && missingDependencies.Count() == 0; + showDisable = categoryName.ToString() != "Core"; + showEnable = missingDependencies.Count() == 0 && feature.Descriptor.Id != "Orchard.Setup";
        • @@ -74,31 +74,64 @@
          }
          - @if (showActions) { - if (feature.IsEnabled) { + @if (showDisable && feature.IsEnabled) { using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Disable", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { @Html.Hidden("id", feature.Descriptor.Id, new {id = ""}) @Html.Hidden("force", true) } } - else { + + @if(showEnable && !feature.IsEnabled) { using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Enable", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { @Html.Hidden("id", feature.Descriptor.Id, new { id = "" }) @Html.Hidden("force", true) } } - } - @if(feature.NeedsUpdate){ - using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Update", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { - @Html.Hidden("id", feature.Descriptor.Id, new { id = "" }) - + + @if(feature.NeedsUpdate){ + using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Update", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { + @Html.Hidden("id", feature.Descriptor.Id, new { id = "" }) + + } } - }
        • } }
      • } -}
      } \ No newline at end of file +}} + +@using(Script.Foot()) { + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt index 952bbe3c8..95ac79671 100644 --- a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The multi-tenancy module enables multiple Orchard sites to run in isolation inside of a single web application, improving site density on a single server or hosted account. FeatureDescription: Configure multiple site tenants. Category: Hosting diff --git a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Properties/AssemblyInfo.cs index 4e22a1e44..1fe8fc649 100644 --- a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs index d1ddfdc98..6a559ab06 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs @@ -7,6 +7,7 @@ using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; using Orchard.Localization; using Orchard.Logging; +using Orchard.Mvc.Extensions; using Orchard.Packaging.Models; using Orchard.Packaging.Services; using Orchard.Packaging.ViewModels; @@ -44,6 +45,7 @@ namespace Orchard.Packaging.Controllers { Services = services; Shape = shapeFactory; + PackageUpdateService = packageUpdateService; T = NullLocalizer.Instance; Logger = NullLogger.Instance; @@ -53,6 +55,7 @@ namespace Orchard.Packaging.Controllers { public Localizer T { get; set; } public ILogger Logger { get; set; } public dynamic Shape { get; set; } + public IPackageUpdateService PackageUpdateService { get; set; } public ActionResult ThemesUpdates(int? reportId, PagerParameters pagerParameters) { return PackageUpdate("ThemesUpdates", DefaultExtensionTypes.Theme, reportId, pagerParameters); @@ -62,6 +65,15 @@ namespace Orchard.Packaging.Controllers { return PackageUpdate("ModulesUpdates", DefaultExtensionTypes.Module, reportId, pagerParameters); } + public ActionResult ReloadUpdates(string returnUrl) { + _packageUpdateService.TriggerRefresh(); + _backgroundPackageUpdateStatus.Value = null; + + Services.Notifier.Warning(T("The feed has been notified for update. It might take a few minutes before the updates are displayed.")); + + return this.RedirectLocal(returnUrl); + } + private ActionResult PackageUpdate(string view, string extensionType, int? reportId, PagerParameters pagerParameters) { if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources"))) return new HttpUnauthorizedResult(); @@ -86,8 +98,9 @@ namespace Orchard.Packaging.Controllers { IEnumerable updatedPackages = _backgroundPackageUpdateStatus.Value.Entries .Where(updatePackageEntry => - updatePackageEntry.ExtensionsDescriptor.ExtensionType.Equals(extensionType) && - updatePackageEntry.NewVersionToInstall != null); + updatePackageEntry.ExtensionsDescriptor.ExtensionType.Equals(extensionType) && + updatePackageEntry.NewVersionToInstall != null) + .ToList(); int totalItemCount = updatedPackages.Count(); @@ -96,6 +109,7 @@ namespace Orchard.Packaging.Controllers { } return View(view, new PackagingListViewModel { + LastUpdateCheckUtc = _backgroundPackageUpdateStatus.Value.DateTimeUtc, Entries = updatedPackages, Pager = Shape.Pager(pager).TotalItemCount(totalItemCount) }); diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Models/UpdatePackageEntry.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Models/UpdatePackageEntry.cs index 9ee31ba6e..e685c55f3 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Models/UpdatePackageEntry.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Models/UpdatePackageEntry.cs @@ -5,6 +5,7 @@ using Orchard.Environment.Extensions.Models; namespace Orchard.Packaging.Models { public class PackagesStatusResult { + public DateTime DateTimeUtc { get; set; } public IEnumerable Entries { get; set; } public IEnumerable Errors { get; set; } } diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Module.txt b/src/Orchard.Web/Modules/Orchard.Packaging/Module.txt index 9ea20fcdd..fbfd940ad 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The packaging module enables packaging modules using the OPC format. FeatureDescription: Commands for creating/installing local modules. Category: Packaging diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj b/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj index 4e6d95cc0..904c15566 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj @@ -36,7 +36,7 @@ - + False ..\..\..\..\lib\nuget\NuGet.Core.dll True diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Properties/AssemblyInfo.cs index 522f28fc9..2067460dc 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageUpdateManager.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageUpdateManager.cs index 53ea45d0a..b94f58239 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageUpdateManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageUpdateManager.cs @@ -49,6 +49,7 @@ namespace Orchard.Packaging.Services { foreach (var source in sources) { var sourceResult = GetPackages(source); + result.DateTimeUtc = sourceResult.DateTimeUtc; result.Entries = result.Entries.Concat(sourceResult.Entries); result.Errors = result.Errors.Concat(sourceResult.Errors); } @@ -61,14 +62,15 @@ namespace Orchard.Packaging.Services { } private PackagesStatusResult GetPackages(PackagingSource packagingSource) { + // Refresh every 23 hours or when signal was triggered return _cacheManager.Get(packagingSource.FeedUrl, ctx => { - // Refresh every minute or when signal was triggered - ctx.Monitor(_clock.When(TimeSpan.FromMinutes(5))); + ctx.Monitor(_clock.When(TimeSpan.FromMinutes(60 * 23))); ctx.Monitor(_signals.When("PackageUpdateService")); // We cache exception because we are calling on a network feed, and failure may // take quite some time. var result = new PackagesStatusResult { + DateTimeUtc = _clock.UtcNow, Entries = new List(), Errors = new List() }; diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs index 5adc82fbb..5963b1e5f 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using Orchard.Data; using Orchard.Environment.Extensions; using Orchard.Localization; @@ -43,7 +44,7 @@ namespace Orchard.Packaging.Services { /// The feed url. /// The feed identifier. public int AddSource(string feedTitle, string feedUrl) { - PackagingSource packagingSource = new PackagingSource { FeedTitle = feedTitle, FeedUrl = feedUrl }; + var packagingSource = new PackagingSource { FeedTitle = feedTitle, FeedUrl = feedUrl }; _packagingSourceRecordRepository.Create(packagingSource); @@ -70,20 +71,29 @@ namespace Orchard.Packaging.Services { /// The list of extensions. public IEnumerable GetExtensionList(bool includeScreenshots, PackagingSource packagingSource = null, Func, IQueryable> query = null) { return (packagingSource == null ? GetSources() : new[] {packagingSource}) - .SelectMany( - source => { - var galleryFeedContext = new GalleryFeedContext(new Uri(source.FeedUrl)) { IgnoreMissingProperties = true }; - IQueryable packages = includeScreenshots - ? galleryFeedContext.Packages.Expand("Screenshots") - : galleryFeedContext.Packages; - - if (query != null) { - packages = query(packages); - } + .SelectMany(source => GetExtensionListFromSource(includeScreenshots, packagingSource, query, source)); + } - return packages.ToList().Select(p => CreatePackageEntry(p, packagingSource, galleryFeedContext.GetReadStreamUri(p))); - } - ); + private static IEnumerable GetExtensionListFromSource(bool includeScreenshots, PackagingSource packagingSource, Func, IQueryable> query, PackagingSource source) { + var galleryFeedContext = new GalleryFeedContext(new Uri(source.FeedUrl)) { IgnoreMissingProperties = true }; + + // Setup compression + galleryFeedContext.SendingRequest += (o, e) => { + if (e.Request is HttpWebRequest) { + (e.Request as HttpWebRequest).AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + }; + + // Include screenshots if needed + IQueryable packages = includeScreenshots + ? galleryFeedContext.Packages.Expand("Screenshots") + : galleryFeedContext.Packages; + + if (query != null) { + packages = query(packages); + } + + return packages.ToList().Select(p => CreatePackageEntry(p, packagingSource, galleryFeedContext.GetReadStreamUri(p))); } /// @@ -110,7 +120,7 @@ namespace Orchard.Packaging.Services { #endregion private static PackagingEntry CreatePackageEntry(PublishedPackage package, PackagingSource source, Uri downloadUri) { - Uri baseUri = new Uri(string.Format("{0}://{1}:{2}/", + var baseUri = new Uri(string.Format("{0}://{1}:{2}/", downloadUri.Scheme, downloadUri.Host, downloadUri.Port)); diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Styles/orchard-packaging-admin.css b/src/Orchard.Web/Modules/Orchard.Packaging/Styles/orchard-packaging-admin.css index 42b940466..99460b869 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Styles/orchard-packaging-admin.css +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Styles/orchard-packaging-admin.css @@ -81,4 +81,10 @@ display: inline; height: auto; padding-top: 0; +} +.update-actions { + float: right; + display: inline; + height: auto; + padding-top: 0; } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingListViewModel.cs b/src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingListViewModel.cs index 3b8d45003..eaf19fe05 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingListViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingListViewModel.cs @@ -1,8 +1,10 @@ +using System; using System.Collections.Generic; using Orchard.Packaging.Models; namespace Orchard.Packaging.ViewModels { public class PackagingListViewModel { + public DateTime? LastUpdateCheckUtc { get; set; } public IEnumerable Entries { get; set; } public dynamic Pager { get; set; } } diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ModulesUpdates.cshtml b/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ModulesUpdates.cshtml index eeed4a602..eb4863754 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ModulesUpdates.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ModulesUpdates.cshtml @@ -25,6 +25,10 @@ } } +
      + @T("Check for Updates") +
      + @if (Model.Entries.Count() <= 0) {

      @T("No module updates available.").ToString()

      } else { diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ThemesUpdates.cshtml b/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ThemesUpdates.cshtml index 7c153362a..ce0031b1f 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ThemesUpdates.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Views/GalleryUpdates/ThemesUpdates.cshtml @@ -25,6 +25,10 @@ } } +
      + @T("Check for Updates") +
      + @if (Model.Entries.Count() <= 0) {

      @T("No theme updates available.").ToString()

      } else { diff --git a/src/Orchard.Web/Modules/Orchard.Pages/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Pages/Migrations.cs index 53d7c466d..202c5297c 100644 --- a/src/Orchard.Web/Modules/Orchard.Pages/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Pages/Migrations.cs @@ -8,13 +8,18 @@ namespace Orchard.Pages { ContentDefinitionManager.AlterTypeDefinition("Page", cfg => cfg .WithPart("CommonPart", p => p - .WithSetting("CommonTypePartSettings.ShowCreatedUtcEditor", "true")) + .WithSetting("DateEditorSettings.ShowDateEditor", "true")) .WithPart("PublishLaterPart") .WithPart("RoutePart") .WithPart("BodyPart") .Creatable()); - return 1; + return 2; + } + + public int UpdateFrom1() { + ContentDefinitionManager.AlterTypeDefinition("Page", cfg => cfg.WithPart("CommonPart", p => p.WithSetting("DateEditorSettings.ShowDateEditor", "true"))); + return 2; } } } diff --git a/src/Orchard.Web/Modules/Orchard.Pages/Module.txt b/src/Orchard.Web/Modules/Orchard.Pages/Module.txt index 553c7cc53..fc23883b9 100644 --- a/src/Orchard.Web/Modules/Orchard.Pages/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Pages/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Introduces a preconfigured page content type. FeatureDescription: A basic page content type. Dependencies: Contents diff --git a/src/Orchard.Web/Modules/Orchard.Pages/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Pages/Properties/AssemblyInfo.cs index 8416fd930..a5bd7155d 100644 --- a/src/Orchard.Web/Modules/Orchard.Pages/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Pages/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Module.txt b/src/Orchard.Web/Modules/Orchard.PublishLater/Module.txt index f25e037c4..fbd64f355 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Module.txt @@ -3,8 +3,8 @@ Path: PublishLater AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The PublishLater module introduces draft creation and scheduled publishing functionality. FeatureDescription: Draft creation and scheduled publishing. Category: Content diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.PublishLater/Properties/AssemblyInfo.cs index e5461665c..b3d33165f 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/Commands/RecipesCommands.cs b/src/Orchard.Web/Modules/Orchard.Recipes/Commands/RecipesCommands.cs index 343c9962f..8d00bf214 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/Commands/RecipesCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.Recipes/Commands/RecipesCommands.cs @@ -28,7 +28,7 @@ namespace Orchard.Recipes.Commands { } IEnumerable recipes = _recipeHarvester.HarvestRecipes(extensionId); - if (recipes == null) { + if (recipes.Count() == 0) { throw new OrchardException(T("No recipes found for extension {0}.", extensionId)); } @@ -55,7 +55,7 @@ namespace Orchard.Recipes.Commands { } IEnumerable recipes = _recipeHarvester.HarvestRecipes(extensionId); - if (recipes == null) { + if (recipes.Count() == 0) { throw new OrchardException(T("No recipes found for extension {0}.", extensionId)); } diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/Module.txt b/src/Orchard.Web/Modules/Orchard.Recipes/Module.txt index d8518304e..f6ab26a85 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Recipes/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Provides Orchard Recipes. FeatureDescription: Implementation of Orchard recipes. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Recipes/Properties/AssemblyInfo.cs index 9b09cb6f2..a334ac4b3 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Recipes/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Module.txt b/src/Orchard.Web/Modules/Orchard.Roles/Module.txt index 463765382..a528608d6 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Roles/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The roles module is adding the ability to assign roles to users. It's also providing a set of default roles for which other modules can define default permissions. FeatureDescription: Standard user roles. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Roles/Properties/AssemblyInfo.cs index ef9cc8843..678b4e6f9 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Roles/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs b/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs index 70c68deae..583720fa6 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs +++ b/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs @@ -64,9 +64,16 @@ namespace Orchard.Roles.Services { rolesToExamine = AnonymousRole; } else if (context.User.Has()) { - rolesToExamine = context.User.As().Roles.Concat(AuthenticatedRole); + // the current user is not null, so get his roles and add "Authenticated" to it + rolesToExamine = context.User.As().Roles; + + // when it is a simulated anonymous user in the admin + if (!rolesToExamine.Contains(AnonymousRole[0])) { + rolesToExamine = rolesToExamine.Concat(AuthenticatedRole); + } } else { + // the user is not null and has no specific role, then it's just "Authenticated" rolesToExamine = AuthenticatedRole; } diff --git a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Module.txt b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Module.txt index 3990366af..f4316878c 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The DLR scripting module enables the possibility to execute scripts using the DLR. FeatureDescription: DLR scripting support. Dependencies: Orchard.Scripting diff --git a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Properties/AssemblyInfo.cs index 8a4d76322..482192cfa 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Scripting.Dlr")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Scripting.Dlr")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2019")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/Module.txt b/src/Orchard.Web/Modules/Orchard.Scripting/Module.txt index bef4d8a73..7557147f9 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Scripting/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The scripting module enables the possibility to execute scripts using a simple custom scripting language. FeatureDescription: Scripting support. Category: Scripting @@ -13,3 +13,8 @@ Features: Description: Custom lightweight and simple scripting language. Dependencies: Orchard.Scripting Category: Scripting + Orchard.Scripting.Rules: + Name: Scripting Rules + Description: Rules for the Scripting modules + Category: Rules + Dependencies: Orchard.Scripting, Orchard.Rules \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/Orchard.Scripting.csproj b/src/Orchard.Web/Modules/Orchard.Scripting/Orchard.Scripting.csproj index 336674180..dfe0bc367 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting/Orchard.Scripting.csproj +++ b/src/Orchard.Web/Modules/Orchard.Scripting/Orchard.Scripting.csproj @@ -14,6 +14,7 @@ Orchard.Scripting v4.0 false + false true @@ -66,6 +67,8 @@ + + diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Scripting/Properties/AssemblyInfo.cs index 0579a38f1..6341ddb7a 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Scripting/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Scripting")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Scripting")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2010")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionActions.cs b/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionActions.cs new file mode 100644 index 000000000..9a971e2f8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionActions.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.Localization; + +namespace Orchard.Scripting.Rules { + public interface IActionProvider : IEventHandler { + void Describe(dynamic describe); + } + + [OrchardFeature("Orchard.Scripting.Rules")] + public class ConditionActions : IActionProvider { + private readonly IEnumerable _evaluators; + + public ConditionActions(IEnumerable evaluators) { + _evaluators = evaluators; + } + + public Localizer T { get; set; } + + public void Describe(dynamic describe) { + Func display = context => new LocalizedString(context.Properties["description"]); + + describe.For("Condition", T("Conditions"), T("Conditions")) + .Element("ScriptCondition", T("Script condition"), T("Evaluates a boolean using a scripting engine."), (Func)Evaluate, display, "ScriptCondition"); + } + + private bool Evaluate(dynamic context) { + var evaluator = _evaluators.FirstOrDefault(); + if (evaluator == null) { + throw new OrchardException(T("There are currently no scripting engine enabled")); + } + + var condition = context.Properties["condition"]; + + // assume condition as True if empty + if (!String.IsNullOrWhiteSpace(condition)) { + var result = evaluator.Evaluate(condition, new List()); + if (!(result is bool)) { + throw new OrchardException(T("Expression is not a boolean value")); + } + + return (bool) result; + } + + return true; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionForms.cs b/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionForms.cs new file mode 100644 index 000000000..82faae52c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Scripting/Rules/ConditionForms.cs @@ -0,0 +1,40 @@ +using System; +using Orchard.DisplayManagement; +using Orchard.Environment.Extensions; +using Orchard.Events; +using Orchard.Localization; + +namespace Orchard.Scripting.Rules { + public interface IFormProvider : IEventHandler { + void Describe(dynamic context); + } + + [OrchardFeature("Orchard.Scripting.Rules")] + public class ConditionForms : IFormProvider { + protected dynamic Shape { get; set; } + public Localizer T { get; set; } + + public ConditionForms(IShapeFactory shapeFactory) { + Shape = shapeFactory; + } + + public void Describe(dynamic context) { + Func form = + shape => Shape.Form( + Id: "ScriptCondition", + _Description: Shape.Textbox( + Id: "description", Name: "description", + Title: T("Description"), + Description: T("Message that will be displayed in the Actions list."), + Classes: new[] { "textMedium" }), + _Condition: Shape.TextArea( + Id: "condition", Name: "condition", + Title: T("Condition"), + Description: T("Enter a valid boolean expression to evaluate."), + Classes: new[] { "tokenized" }) + ); + + context.Form("ScriptCondition", form); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Search/Module.txt b/src/Orchard.Web/Modules/Orchard.Search/Module.txt index e1b97034b..10bcd8436 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Search/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The search module enables the management of the search index and provides the front-end searching user interface. FeatureDescription: Standard interface to Orchard's built-in search. Category: Search diff --git a/src/Orchard.Web/Modules/Orchard.Search/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Search/Properties/AssemblyInfo.cs index 5ef26adf5..db8e80c02 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Search/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Search")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Search")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt index eb18e00b4..417670d39 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt @@ -1,8 +1,8 @@ Name: Setup Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The setup module is creating the application's setup experience. FeatureDescription: Standard site setup. This feature is disabled automatically once setup is over. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs index a5215725c..4a780cd6f 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml index 0353dcfd1..abd3b7380 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml @@ -14,7 +14,7 @@ TinyMce,Orchard.Media,Orchard.MediaPicker,Orchard.PublishLater, Orchard.jQuery,Orchard.Widgets,Orchard.Widgets.PageLayerHinting, Orchard.Scripting,Orchard.Scripting.Lightweight, - PackagingServices,Orchard.Packaging,Gallery.Updates,Orchard.Warmup, + PackagingServices,Orchard.Packaging,Orchard.Warmup, TheThemeMachine" /> diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml index d12d169d3..505243327 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml @@ -10,7 +10,7 @@ + enable="Orchard.jQuery" /> diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml index 15629f964..9721820f8 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml @@ -13,7 +13,7 @@ Orchard.Lists,TinyMce,Orchard.Media,Orchard.MediaPicker,Orchard.PublishLater, Orchard.jQuery,Orchard.Widgets,Orchard.Widgets.PageLayerHinting,Orchard.ContentTypes, Orchard.Scripting,Orchard.Scripting.Lightweight, - PackagingServices,Orchard.Packaging,Gallery.Updates,Orchard.Warmup, + PackagingServices,Orchard.Packaging,Orchard.Warmup, TheThemeMachine" /> diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index 15d7277e0..64f049e63 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -73,7 +73,7 @@ namespace Orchard.Setup.Services { // Framework "Orchard.Framework", // Core - "Common", "Containers", "Contents", "Dashboard", "Feeds", "HomePage", "Navigation", "Reports", "Routable", "Scheduling", "Settings", "Shapes", + "Common", "Containers", "Contents", "Dashboard", "Feeds", "HomePage", "Navigation", "Reports", "Routable", "Scheduling", "Settings", "Shapes", "Title", // Modules "Orchard.Pages", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes", @@ -109,41 +109,49 @@ namespace Orchard.Setup.Services { var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); // initialize database explicitly, and store shell descriptor - var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint); + using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) + { - using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { + using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) + { - // check if the database is already created (in case an exception occured in the second phase) - var shellDescriptorRepository = environment.Resolve>(); - try { - shellDescriptorRepository.Get(x => true); - } - catch { - var schemaBuilder = new SchemaBuilder(environment.Resolve()); - var reportsCoordinator = environment.Resolve(); - - reportsCoordinator.Register("Data Migration", "Setup", "Orchard installation"); - - schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", - table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("DataMigrationClass") - .Column("Version")); - - var dataMigrationManager = environment.Resolve(); - dataMigrationManager.Update("Settings"); - - foreach (var feature in context.EnabledFeatures) { - dataMigrationManager.Update(feature); + // check if the database is already created (in case an exception occured in the second phase) + var shellDescriptorRepository = environment.Resolve>(); + try + { + shellDescriptorRepository.Get(x => true); } + catch + { + var schemaBuilder = new SchemaBuilder(environment.Resolve()); + var reportsCoordinator = environment.Resolve(); - environment.Resolve().UpdateShellDescriptor( - 0, - shellDescriptor.Features, - shellDescriptor.Parameters); + reportsCoordinator.Register("Data Migration", "Setup", "Orchard installation"); + + schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", + table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("DataMigrationClass") + .Column("Version")); + + var dataMigrationManager = environment.Resolve(); + dataMigrationManager.Update("Settings"); + + foreach (var feature in context.EnabledFeatures) + { + dataMigrationManager.Update(feature); + } + + environment.Resolve().UpdateShellDescriptor( + 0, + shellDescriptor.Features, + shellDescriptor.Parameters); + } } } + + // in effect "pump messages" see PostMessage circa 1980 while ( _processingEngine.AreTasksPending() ) _processingEngine.ExecuteNextTask(); @@ -165,7 +173,7 @@ namespace Orchard.Setup.Services { } _shellSettingsManager.SaveSettings(shellSettings); - + return executionId; } diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index 50ddb32f6..5ec43b083 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -51,8 +51,8 @@ namespace Orchard.Setup { builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().As().InstancePerLifetimeScope(); - builder.RegisterType().As().As().InstancePerLifetimeScope(); + builder.RegisterType().As().As().SingleInstance(); + builder.RegisterType().As().As().SingleInstance(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); @@ -65,6 +65,7 @@ namespace Orchard.Setup { builder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerMatchingLifetimeScope("shell"); // setup mode specific implementations of needed service interfaces builder.RegisterType().As().InstancePerLifetimeScope(); @@ -77,23 +78,24 @@ namespace Orchard.Setup { builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().SingleInstance(); // in progress - adding services for display/shape support in setup - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerMatchingLifetimeScope("work"); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); builder.RegisterModule(new ShapeAttributeBindingModule()); } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Controllers/HomeController.cs b/src/Orchard.Web/Modules/Orchard.Tags/Controllers/HomeController.cs index 63cff0658..4e120966e 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Controllers/HomeController.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Controllers/HomeController.cs @@ -16,7 +16,6 @@ namespace Orchard.Tags.Controllers { private readonly ITagService _tagService; private readonly IContentManager _contentManager; private readonly ISiteService _siteService; - private readonly dynamic _shapeFactory; public HomeController( ITagService tagService, @@ -26,12 +25,13 @@ namespace Orchard.Tags.Controllers { _tagService = tagService; _contentManager = contentManager; _siteService = siteService; - _shapeFactory = shapeFactory; + Shape = shapeFactory; T = NullLocalizer.Instance; } public ILogger Logger { get; set; } public Localizer T { get; set; } + public dynamic Shape { get; set; } public ActionResult Index() { var tags = _tagService.GetTags(); @@ -48,17 +48,17 @@ namespace Orchard.Tags.Controllers { return RedirectToAction("Index"); } - var taggedItems = _tagService.GetTaggedContentItems(tag.Id, pager.GetStartIndex(), pager.PageSize) - .Select(item => _contentManager.BuildDisplay(item, "Summary")); + var taggedItems = _tagService.GetTaggedContentItems(tag.Id, pager.GetStartIndex(), pager.PageSize).ToList(); + var tagShapes = taggedItems.Select(item => _contentManager.BuildDisplay(item, "Summary")); - var list = _shapeFactory.List(); - list.AddRange(taggedItems); + var list = Shape.List(); + list.AddRange(tagShapes); var totalItemCount = _tagService.GetTaggedContentItemCount(tag.Id); var viewModel = new TagsSearchViewModel { TagName = tag.TagName, List = list, - Pager = _shapeFactory.Pager(pager).TotalItemCount(totalItemCount) + Pager = Shape.Pager(pager).TotalItemCount(totalItemCount) }; return View(viewModel); diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs index b55507416..2b2c5d830 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs @@ -4,7 +4,6 @@ using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; -using Orchard.Security; using Orchard.Tags.Helpers; using Orchard.Tags.Models; using Orchard.Tags.Services; @@ -15,15 +14,9 @@ namespace Orchard.Tags.Drivers { public class TagsPartDriver : ContentPartDriver { private const string TemplateName = "Parts/Tags"; private readonly ITagService _tagService; - private readonly IAuthorizationService _authorizationService; - private readonly IOrchardServices _orchardServices; - public TagsPartDriver(ITagService tagService, - IAuthorizationService authorizationService, - IOrchardServices orchardServices) { + public TagsPartDriver(ITagService tagService) { _tagService = tagService; - _authorizationService = authorizationService; - _orchardServices = orchardServices; } protected override string Prefix { diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs index 5a7d1652e..af5b2bff3 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Models/ContentTagRecord.cs @@ -1,7 +1,12 @@ +using Orchard.Data.Conventions; + namespace Orchard.Tags.Models { public class ContentTagRecord { public virtual int Id { get; set; } + + [Aggregate] public virtual TagRecord TagRecord { get; set; } + public virtual TagsPartRecord TagsPartRecord { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs index 4687757be..19aabe193 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Models/TagsPartRecord.cs @@ -1,11 +1,14 @@ using System.Collections.Generic; using Orchard.ContentManagement.Records; +using Orchard.Data.Conventions; namespace Orchard.Tags.Models { public class TagsPartRecord : ContentPartRecord { public TagsPartRecord() { Tags = new List(); } + + [Aggregate] public virtual IList Tags { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt index 328308fa1..62cf79b30 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The tags module is providing basic tagging for arbitrary content types. FeatureDescription: Tag a content item. Dependencies: Settings diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs index a3799d043..7027a134d 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs index 426c14b91..31ad4b681 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagService.cs @@ -177,15 +177,14 @@ namespace Orchard.Tags.Services { var tags = tagNamesForContentItem.Select(CreateTag); var newTagsForContentItem = new List(tags); - var currentTagsForContentItem = _contentTagRepository.Fetch(x => x.TagsPartRecord.Id == contentItem.Id); + var currentTagsForContentItem = contentItem.As().Record.Tags; foreach (var tagContentItem in currentTagsForContentItem) { if (!newTagsForContentItem.Contains(tagContentItem.TagRecord)) { _contentTagRepository.Delete(tagContentItem); } - else { - newTagsForContentItem.Remove(tagContentItem.TagRecord); - } + + newTagsForContentItem.Remove(tagContentItem.TagRecord); } foreach (var newTagForContentItem in newTagsForContentItem) { diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt index 164dbf7c0..b36a59aec 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The themes module makes it possible for Orchard applications to customize the look and feel of an Orchard web site. FeatureDescription: Basic theming capability. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs index ba7cdeed2..20a49c9c7 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Themes/ResourceManifest.cs b/src/Orchard.Web/Modules/Orchard.Themes/ResourceManifest.cs index ca8e66da4..6e2c80937 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/ResourceManifest.cs +++ b/src/Orchard.Web/Modules/Orchard.Themes/ResourceManifest.cs @@ -5,10 +5,6 @@ namespace Orchard.Themes { public void BuildManifests(ResourceManifestBuilder builder) { var manifest = builder.Add(); manifest.DefineStyle("ThemesAdmin").SetUrl("orchard-themes-admin.css"); - - // todo: include and define the min.js version too - // todo: move EasySlider to common location, although it does not appear to be used anywhere right now - manifest.DefineScript("EasySlider").SetUrl("~/themes/contoso/scripts/easySlider.js").SetDependencies("jQuery"); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs index e0cd96257..395d29524 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs @@ -4,13 +4,13 @@ using System.Text.RegularExpressions; using System.Web.Mvc; using System.Web.Routing; using Orchard.ContentManagement; -using Orchard.Core.Common.Models; using Orchard.Core.Contents.Controllers; using Orchard.Core.Settings.Models; using Orchard.DisplayManagement; using Orchard.Localization; using Orchard.Security; using Orchard.UI.Notify; +using Orchard.Users.Events; using Orchard.Users.Models; using Orchard.Users.Services; using Orchard.Users.ViewModels; @@ -24,6 +24,7 @@ namespace Orchard.Users.Controllers { public class AdminController : Controller, IUpdateModel { private readonly IMembershipService _membershipService; private readonly IUserService _userService; + private readonly IEnumerable _userEventHandlers; private readonly ISiteService _siteService; public AdminController( @@ -31,10 +32,12 @@ namespace Orchard.Users.Controllers { IMembershipService membershipService, IUserService userService, IShapeFactory shapeFactory, + IEnumerable userEventHandlers, ISiteService siteService) { Services = services; _membershipService = membershipService; _userService = userService; + _userEventHandlers = userEventHandlers; _siteService = siteService; T = NullLocalizer.Instance; @@ -311,6 +314,9 @@ namespace Orchard.Users.Controllers { if ( user != null ) { user.As().RegistrationStatus = UserStatus.Approved; Services.Notifier.Information(T("User {0} approved", user.UserName)); + foreach (var userEventHandler in _userEventHandlers) { + userEventHandler.Approved(user); + } } return RedirectToAction("Index"); diff --git a/src/Orchard.Web/Modules/Orchard.Users/Events/IUserEventHandler.cs b/src/Orchard.Web/Modules/Orchard.Users/Events/IUserEventHandler.cs index d6bbbb634..6823c332e 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Events/IUserEventHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Events/IUserEventHandler.cs @@ -19,7 +19,7 @@ namespace Orchard.Users.Events { void LoggedIn(IUser user); /// - /// Called when a user explicitly logs out (as opposed to one whos session cookie simply expires) + /// Called when a user explicitly logs out (as opposed to one whose session cookie simply expires) /// void LoggedOut(IUser user); @@ -42,6 +42,11 @@ namespace Orchard.Users.Events { /// Called after a user has confirmed their email address ///
      void ConfirmedEmail(IUser user); + + /// + /// Called after a user has been approved + /// + void Approved(IUser user); } } diff --git a/src/Orchard.Web/Modules/Orchard.Users/Module.txt b/src/Orchard.Web/Modules/Orchard.Users/Module.txt index 2d3334f67..0f21854b6 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Users/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The users module enables user management. FeatureDescription: Standard users. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj index b1168aa0a..4dbe24a3c 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj +++ b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj @@ -18,6 +18,7 @@ 3.5 + false true @@ -70,6 +71,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs index 58cdc1ef6..57d796ec4 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Users/Security/AccessFrontEndFilter.cs b/src/Orchard.Web/Modules/Orchard.Users/Security/AccessFrontEndFilter.cs new file mode 100644 index 000000000..efcadfdc7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Users/Security/AccessFrontEndFilter.cs @@ -0,0 +1,31 @@ +using System.Web.Mvc; +using Orchard.Localization; +using Orchard.Mvc.Filters; +using Orchard.Security; +using Orchard.UI.Admin; + +namespace Orchard.Users.Security { + public class FrontEndFilter : FilterProvider, IAuthorizationFilter { + private readonly IAuthorizer _authorizer; + + public FrontEndFilter(IAuthorizer authorizer) { + _authorizer = authorizer; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + public void OnAuthorization(AuthorizationContext filterContext) { + + var isAuthPage = (filterContext.ActionDescriptor.ActionName == "LogOn" + || filterContext.ActionDescriptor.ActionName == "ChangePassword" + || filterContext.ActionDescriptor.ActionName == "AccessDenied" + || filterContext.ActionDescriptor.ActionName == "Register") + && filterContext.ActionDescriptor.ControllerDescriptor.ControllerName == "Account"; + + if (!AdminFilter.IsApplied(filterContext.RequestContext) && !isAuthPage && !_authorizer.Authorize(StandardPermissions.AccessFrontEnd, T("Can't access this website"))) { + filterContext.Result = new HttpUnauthorizedResult(); + } + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs b/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs index 6af141c6e..1ddf75af7 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs @@ -76,6 +76,9 @@ namespace Orchard.Users.Services { foreach ( var userEventHandler in _userEventHandlers ) { userEventHandler.Created(userContext); + if (user.RegistrationStatus == UserStatus.Approved) { + userEventHandler.Approved(user); + } } if ( registrationSettings != null && registrationSettings.UsersAreModerated && registrationSettings.NotifyModeration && !createUserParams.IsApproved ) { diff --git a/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt b/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt index 14d540d8c..943757c43 100644 --- a/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: Provides a mecanism to generate a static version of pages for being used during application warm up. FeatureDescription: Generates the static version of specific pages periodically. Category: Hosting diff --git a/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs index 85e7ba2df..5c208c370 100644 --- a/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -9,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("Orchard")] -[assembly: AssemblyCopyright("")] +[assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,5 +31,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] +[assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs index e7aeb6d9e..295c00576 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs @@ -70,6 +70,13 @@ namespace Orchard.Widgets.Filters { Logger.Warning("The widget '{0}' is has no assigned layer or the layer does not exist.", widgetPart.Title); continue; } + + // ignore widget for different cultures + var localizablePart = widgetPart.As(); + if (localizablePart != null && localizablePart.Culture != workContext.CurrentCulture) { + continue; + } + if (activeLayerIds.Contains(commonPart.Container.ContentItem.Id)) { var widgetShape = _contentManager.BuildDisplay(widgetPart); zones[widgetPart.Record.Zone].Add(widgetShape, widgetPart.Record.Position); diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs index bc67ce6fa..b03acdf05 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs @@ -5,7 +5,7 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; namespace Orchard.Widgets.Models { - public class WidgetPart : ContentPart { + public class WidgetPart : ContentPart, ITitleAspect { /// /// The widget's title. diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt b/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt index 2e0b12c9a..0400b2918 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt @@ -2,8 +2,8 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: An implementation of widgets for Orchard. FeatureDescription: An implementation of widgets. Category: Widget diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs index 281e18d17..f66e447f2 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Security; [assembly: AssemblyTitle("Orchard.Widgets")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard.Widgets")] +[assembly: AssemblyProduct("Orchard")] [assembly: AssemblyCopyright("Copyright © Outercurve Foundation 2009")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Module.txt b/src/Orchard.Web/Modules/Orchard.jQuery/Module.txt index aa6ec9367..69577f01d 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Module.txt @@ -3,8 +3,8 @@ Path: Orchard.jQuery AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.2.41 -OrchardVersion: 1.2.41 +Version: 1.3.0 +OrchardVersion: 1.3.0 Description: The jQuery module contains the jQuery and related script libraries. FeatureDescription: A common location for jQuery and related script libraries. Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj b/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj index b3fdfe20b..7b0b3286d 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj @@ -47,8 +47,8 @@ - - + + diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.jQuery/Properties/AssemblyInfo.cs index 153e55a8e..e619fbb40 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.41")] -[assembly: AssemblyFileVersion("1.2.41")] +[assembly: AssemblyVersion("1.3.0")] +[assembly: AssemblyFileVersion("1.3.0")] [assembly: SecurityTransparent] diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs b/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs index 3ba4ad362..4949e5b5c 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs +++ b/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs @@ -4,7 +4,7 @@ namespace Orchard.jQuery { public class ResourceManifest : IResourceManifestProvider { public void BuildManifests(ResourceManifestBuilder builder) { var manifest = builder.Add(); - manifest.DefineScript("jQuery").SetUrl("jquery-1.6.1.min.js", "jquery-1.6.1.js").SetVersion("1.6.1"); + manifest.DefineScript("jQuery").SetUrl("jquery-1.6.4.min.js", "jquery-1.6.4.js").SetVersion("1.6.4"); // UI Core manifest.DefineScript("jQueryUI_Core").SetUrl("jquery.ui.core.min.js", "jquery.ui.core.js").SetVersion("1.8.10").SetDependencies("jQuery"); @@ -24,7 +24,7 @@ namespace Orchard.jQuery { manifest.DefineScript("jQueryUI_Autocomplete").SetUrl("jquery.ui.autocomplete.min.js", "jquery.ui.autocomplete.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget", "jQueryUI_Position"); manifest.DefineScript("jQueryUI_Button").SetUrl("jquery.ui.button.min.js", "jquery.ui.button.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget"); manifest.DefineScript("jQueryUI_Dialog").SetUrl("jquery.ui.dialog.min.js", "jquery.ui.dialog.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget", "jQueryUI_Position", "jQueryUI_Mouse", "jQueryUI_Draggable", "jQueryUI_Resizable"); - manifest.DefineScript("jQueryUI_Slider").SetUrl("jquery.ui.slidder.min.js", "jquery.ui.slidder.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget", "jQueryUI_Mouse"); + manifest.DefineScript("jQueryUI_Slider").SetUrl("jquery.ui.slider.min.js", "jquery.ui.slider.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget", "jQueryUI_Mouse"); manifest.DefineScript("jQueryUI_Tabs").SetUrl("jquery.ui.tabs.min.js", "jquery.ui.tabs.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget"); manifest.DefineScript("jQueryUI_DatePicker").SetUrl("jquery.ui.datepicker.min.js", "jquery.ui.datepicker.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core"); manifest.DefineScript("jQueryUI_Progressbar").SetUrl("jquery.ui.progressbar.min.js", "jquery.ui.progressbar.js").SetVersion("1.8.10").SetDependencies("jQueryUI_Core", "jQueryUI_Widget"); diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.min.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.min.js deleted file mode 100644 index 1790d3366..000000000 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.min.js +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu May 12 15:04:36 2011 -0400 - */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!cj[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),c.body.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write("");b=cl.createElement(a),cl.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ck)}cj[a]=d}return cj[a]}function cu(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function ct(){cq=b}function cs(){setTimeout(ct,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g=0===c})}function W(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function O(a,b){return(a&&a!=="*"?a+".":"")+b.replace(A,"`").replace(B,"&")}function N(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function L(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function F(){return!0}function E(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
      a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};f=c.createElement("select"),g=f.appendChild(c.createElement("option")),h=a.getElementsByTagName("input")[0],j={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},h.checked=!0,j.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,j.optDisabled=!g.disabled;try{delete a.test}catch(s){j.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function b(){j.noCloneEvent=!1,a.detachEvent("onclick",b)}),a.cloneNode(!0).fireEvent("onclick")),h=c.createElement("input"),h.value="t",h.setAttribute("type","radio"),j.radioValue=h.value==="t",h.setAttribute("checked","checked"),a.appendChild(h),k=c.createDocumentFragment(),k.appendChild(a.firstChild),j.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",l=c.createElement("body"),m={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(q in m)l.style[q]=m[q];l.appendChild(a),b.insertBefore(l,b.firstChild),j.appendChecked=h.checked,j.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,j.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
      ",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
      t
      ",n=a.getElementsByTagName("td"),r=n[0].offsetHeight===0,n[0].style.display="",n[1].style.display="none",j.reliableHiddenOffsets=r&&n[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(i=c.createElement("div"),i.style.width="0",i.style.marginRight="0",a.appendChild(i),j.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(i,null)||{marginRight:0}).marginRight,10)||0)===0),l.innerHTML="",b.removeChild(l);if(a.attachEvent)for(q in{submit:1,change:1,focusin:1})p="on"+q,r=p in a,r||(a.setAttribute(p,"return;"),r=typeof a[p]=="function"),j[q+"Bubbles"]=r;return j}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c],i||(!t.test(c)||typeof d!="boolean"&&d!==b&&d.toLowerCase()!==c.toLowerCase()?v&&(f.nodeName(a,"form")||u.test(c))&&(i=v):i=w);if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},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(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return a[f.propFix[c]||c]?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=b),a.setAttribute(c,c.toLowerCase()));return c}},f.attrHooks.value={get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return a.value},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=Object.prototype.hasOwnProperty,y=/\.(.*)$/,z=/^(?:textarea|input|select)$/i,A=/\./g,B=/ /g,C=/[^\w\s.|`]/g,D=function(a){return a.replace(C,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=E;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=E);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),D).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem -)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},K=function(c){var d=c.target,e,g;if(!!z.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=J(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:K,beforedeactivate:K,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&K.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&K.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",J(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in I)f.event.add(this,c+".specialChange",I[c]);return z.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return z.test(this.nodeName)}},I=f.event.special.change.filters,I.focus=I.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

      ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
      ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=U.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(W(c[0])||W(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=T.call(arguments);P.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!V[a]?f.unique(e):e,(this.length>1||R.test(d))&&Q.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y=/ jQuery\d+="(?:\d+|null)"/g,Z=/^\s+/,$=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,_=/<([\w:]+)/,ba=/",""],legend:[1,"
      ","
      "],thead:[1,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],col:[2,"","
      "],area:[1,"",""],_default:[0,"",""]};bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
      ","
      "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(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,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Y,""):null;if(typeof a=="string"&&!bc.test(a)&&(f.support.leadingWhitespace||!Z.test(a))&&!bg[(_.exec(a)||["",""])[1].toLowerCase()]){a=a.replace($,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bj(a,d),e=bk(a),g=bk(d);for(h=0;e[h];++h)bj(e[h],g[h])}if(b){bi(a,d);if(c){e=bk(a),g=bk(d);for(h=0;e[h];++h)bi(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument|| -b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bb.test(k))k=b.createTextNode(k);else{k=k.replace($,"<$1>");var l=(_.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=ba.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Z.test(k)&&o.insertBefore(b.createTextNode(Z.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bp.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bo.test(g)?g.replace(bo,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,c){var d,e,g;c=c.replace(br,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bs.test(d)&&bt.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bE=/%20/g,bF=/\[\]$/,bG=/\r?\n/g,bH=/#.*$/,bI=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bJ=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bK=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bL=/^(?:GET|HEAD)$/,bM=/^\/\//,bN=/\?/,bO=/)<[^<]*)*<\/script>/gi,bP=/^(?:select|textarea)/i,bQ=/\s+/,bR=/([?&])_=[^&]*/,bS=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bT=f.fn.load,bU={},bV={},bW,bX;try{bW=e.href}catch(bY){bW=c.createElement("a"),bW.href="",bW=bW.href}bX=bS.exec(bW.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bT)return bT.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
      ").append(c.replace(bO,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bP.test(this.nodeName)||bJ.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bG,"\r\n")}}):{name:b.name,value:c.replace(bG,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bW,isLocal:bK.test(bX[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bZ(bU),ajaxTransport:bZ(bV),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?ca(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=cb(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bI.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bH,"").replace(bM,bX[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bQ),d.crossDomain==null&&(r=bS.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bX[1]&&r[2]==bX[2]&&(r[3]||(r[1]==="http:"?80:443))==(bX[3]||(bX[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bU,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bL.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bN.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bR,"$1_="+x);d.url=y+(y===d.url?(bN.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bV,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bE,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq,cr=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
      ";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.4.js similarity index 92% rename from src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.js rename to src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.4.js index 0451f6ec2..11e6d0679 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.1.js +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery-1.6.4.js @@ -1,8936 +1,9046 @@ -/*! - * jQuery JavaScript Library v1.6.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu May 12 15:04:36 2011 -0400 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document, - navigator = window.navigator, - location = window.location; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // The deferred used on DOM ready - readyList, - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - 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 = quickExpr.exec( selector ); - } - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - 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.6.1", - - // 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 slice.call( this, 0 ); - }, - - // 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 = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, 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 ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( 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( slice.apply( this, arguments ), - "slice", 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: 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 ) { - // Either a released hold or an DOMready/load event and not yet ready - if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { - // 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" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = jQuery._Deferred(); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - 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 if ( document.attachEvent ) { - // 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 toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // 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"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ 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; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - 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 || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - 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 - // (xml & tmp used internally) - parseXML: function( data , xml , tmp ) { - - 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 ); - } - - tmp = xml.documentElement; - - if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { - 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 && 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 ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction( object ); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { - break; - } - } - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - - if ( indexOf ) { - return indexOf.call( array, elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; 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 ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; 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 ) { - if ( typeof context === "string" ) { - var 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 - var args = slice.call( arguments, 2 ), - proxy = function() { - return fn.apply( context, args.concat( 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 || proxy.guid || jQuery.guid++; - - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can be optionally by executed if its a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - 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; - }, - - browser: {} -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -// Expose jQuery to the global object -return jQuery; - -})(); - - -var // Promise methods - promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), - // Static reference to slice - sliceDeferred = [].slice; - -jQuery.extend({ - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - // make sure args are available (#8421) - args = args || []; - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - always: function() { - return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - pipe: function( fnDone, fnFail ) { - return jQuery.Deferred(function( newDefer ) { - jQuery.each( { - done: [ fnDone, "resolve" ], - fail: [ fnFail, "reject" ] - }, function( handler, data ) { - var fn = data[ 0 ], - action = data[ 1 ], - returned; - if ( jQuery.isFunction( fn ) ) { - deferred[ handler ](function() { - returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise().then( newDefer.resolve, newDefer.reject ); - } else { - newDefer[ action ]( returned ); - } - }); - } else { - deferred[ handler ]( newDefer[ action ] ); - } - }); - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - }); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( firstParam ) { - var args = arguments, - i = 0, - length = args.length, - count = length, - deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? - firstParam : - jQuery.Deferred(); - function resolveFunc( i ) { - return function( value ) { - args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - if ( !( --count ) ) { - // Strange bug in FF4: - // Values changed onto the arguments object sometimes end up as undefined values - // outside the $.when method. Cloning the object into a fresh array solves the issue - deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); - } - }; - } - if ( length > 1 ) { - for( ; i < length; i++ ) { - if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { - args[ i ].promise().then( resolveFunc(i), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( deferred, args ); - } - } else if ( deferred !== firstParam ) { - deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); - } - return deferred.promise(); - } -}); - - - -jQuery.support = (function() { - - var div = document.createElement( "div" ), - documentElement = document.documentElement, - all, - a, - select, - opt, - input, - marginDiv, - support, - fragment, - body, - bodyStyle, - tds, - events, - eventName, - i, - isSupported; - - // Preliminary tests - div.setAttribute("className", "t"); - div.innerHTML = "
      a"; - - all = div.getElementsByTagName( "*" ); - a = div.getElementsByTagName( "a" )[ 0 ]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - 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.55$/.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", - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true - }; - - // 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", function click() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - div.detachEvent( "onclick", click ); - }); - div.cloneNode( true ).fireEvent( "onclick" ); - } - - // Check if a radio maintains it's 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"); - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - div.innerHTML = ""; - - // Figure out if the W3C box model works as expected - div.style.width = div.style.paddingLeft = "1px"; - - // We use our own, invisible, body - body = document.createElement( "body" ); - bodyStyle = { - visibility: "hidden", - width: 0, - height: 0, - border: 0, - margin: 0, - // Set background to avoid IE crashes when removing (#9028) - background: "none" - }; - for ( i in bodyStyle ) { - body.style[ i ] = bodyStyle[ i ]; - } - body.appendChild( div ); - documentElement.insertBefore( body, documentElement.firstChild ); - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // 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.style.display = "inline"; - div.style.zoom = 1; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
      "; - support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); - } - - div.innerHTML = "
      t
      "; - tds = div.getElementsByTagName( "td" ); - - // 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) - 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 ); - div.innerHTML = ""; - - // 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 - if ( document.defaultView && document.defaultView.getComputedStyle ) { - marginDiv = document.createElement( "div" ); - marginDiv.style.width = "0"; - marginDiv.style.marginRight = "0"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; - } - - // Remove the body element we added - body.innerHTML = ""; - documentElement.removeChild( body ); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/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: 1, - change: 1, - focusin: 1 - } ) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - return support; -})(); - -// Keep track of boxModel -jQuery.boxModel = jQuery.support.boxModel; - - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/, - rmultiDash = /([a-z])([A-Z])/g; - -jQuery.extend({ - cache: {}, - - // Please use with caution - 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 internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, - - // 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[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // 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 || (pvt && id && !cache[ id ][ internalKey ])) && 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[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // TODO: This is a hack for 1.5 ONLY. 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 ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - 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 ) { - var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !isEmptyDataObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - if ( jQuery.support.deleteExpando || cache != window ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // 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 ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = 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 ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - 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-$2" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( 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; -} - -// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON -// property to be considered empty objects; this property always exists in -// order to make sure JSON.stringify does not expose internal metadata -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -function handleQueueMarkDefer( elem, type, src ) { - var deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - defer = jQuery.data( elem, deferDataKey, undefined, true ); - if ( defer && - ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && - ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { - // Give room for hard-coded callbacks to fire first - // and eventually mark/queue something else on the element - setTimeout( function() { - if ( !jQuery.data( elem, queueDataKey, undefined, true ) && - !jQuery.data( elem, markDataKey, undefined, true ) ) { - jQuery.removeData( elem, deferDataKey, true ); - defer.resolve(); - } - }, 0 ); - } -} - -jQuery.extend({ - - _mark: function( elem, type ) { - if ( elem ) { - type = (type || "fx") + "mark"; - jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); - } - }, - - _unmark: function( force, elem, type ) { - if ( force !== true ) { - type = elem; - elem = force; - force = false; - } - if ( elem ) { - type = type || "fx"; - var key = type + "mark", - count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); - if ( count ) { - jQuery.data( elem, key, count, true ); - } else { - jQuery.removeData( elem, key, true ); - handleQueueMarkDefer( elem, type, "mark" ); - } - } - }, - - queue: function( elem, type, data ) { - if ( elem ) { - type = (type || "fx") + "queue"; - var q = jQuery.data( elem, type, undefined, true ); - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !q || jQuery.isArray(data) ) { - q = jQuery.data( elem, type, jQuery.makeArray(data), true ); - } else { - q.push( data ); - } - } - return q || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(), - defer; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - handleQueueMarkDefer( elem, type, "queue" ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function() { - var queue = jQuery.queue( this, type, data ); - - 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() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - 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, object ) { - if ( typeof type !== "string" ) { - object = type; - type = undefined; - } - type = type || "fx"; - var defer = jQuery.Deferred(), - elements = this, - i = elements.length, - count = 1, - deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - tmp; - function resolve() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - } - while( i-- ) { - if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || - ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || - jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && - jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { - count++; - tmp.done( resolve ); - } - } - resolve(); - return defer.promise(); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspace = /\s+/, - 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, - rinvalidChar = /\:/, - formHook, boolHook; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.prop ); - }, - - 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 ) { - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class") || "") ); - }); - } - - if ( value && typeof value === "string" ) { - var classNames = (value || "").split( rspace ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className ) { - elem.className = value; - - } else { - var className = " " + elem.className + " ", - setClass = elem.className; - - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - setClass += " " + classNames[c]; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - var classNames = (value || "").split( rspace ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - var className = (" " + elem.className + " ").replace(rclass, " "); - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[c] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class"), 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( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated 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 + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - return (elem.value || "").replace(rreturn, ""); - } - - return undefined; - } - - var isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var self = jQuery(this), val; - - 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.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; - - // 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, - 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 - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var 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; - } - } - }, - - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attrFix: { - // Always normalize to ensure hook usage - tabindex: "tabIndex" - }, - - attr: function( elem, name, value, pass ) { - var nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( !("getAttribute" in elem) ) { - return jQuery.prop( elem, name, value ); - } - - var ret, hooks, - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // Normalize the name if needed - name = notxml && jQuery.attrFix[ name ] || name; - - hooks = jQuery.attrHooks[ name ]; - - if ( !hooks ) { - // Use boolHook for boolean attributes - if ( rboolean.test( name ) && - (typeof value === "boolean" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) { - - hooks = boolHook; - - // Use formHook for forms and if the name contains certain characters - } else if ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { - hooks = formHook; - } - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return undefined; - - } 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 ) { - return hooks.get( elem, name ); - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, name ) { - var propName; - if ( elem.nodeType === 1 ) { - name = jQuery.attrFix[ name ] || name; - - if ( jQuery.support.getSetAttribute ) { - // Use removeAttribute in browsers that support it - elem.removeAttribute( name ); - } else { - jQuery.attr( elem, name, "" ); - elem.removeAttributeNode( elem.getAttributeNode( name ) ); - } - - // Set corresponding property to false for boolean attributes - if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) 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; - } - } - }, - 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; - } - } - }, - - 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 nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return undefined; - } - - var ret, hooks, - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // Try to normalize/fix the name - name = notxml && 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 )) !== undefined ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: {} -}); - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - return elem[ jQuery.propFix[ name ] || name ] ? - 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 ] = value; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// Use the value property for back compat -// Use the formHook for button elements in IE6/7 (#1954) -jQuery.attrHooks.value = { - get: function( elem, name ) { - if ( formHook && jQuery.nodeName( elem, "button" ) ) { - return formHook.get( elem, name ); - } - return elem.value; - }, - set: function( elem, value, name ) { - if ( formHook && jQuery.nodeName( elem, "button" ) ) { - return formHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !jQuery.support.getSetAttribute ) { - - // propFix is more comprehensive and contains all fixes - jQuery.attrFix = jQuery.propFix; - - // Use this for any attribute on a form in IE6/7 - formHook = jQuery.attrHooks.name = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - // Return undefined if nodeValue is empty string - return ret && ret.nodeValue !== "" ? - ret.nodeValue : - undefined; - }, - set: function( elem, value, name ) { - // Check form objects in IE (multiple bugs related) - // Only use nodeValue if the attribute node exists on the form - var ret = elem.getAttributeNode( name ); - if ( ret ) { - ret.nodeValue = value; - return 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; - } - } - }); - }); -} - - -// 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; - } - } - } - }); -} - -// 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 hasOwn = Object.prototype.hasOwnProperty, - rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspaces = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData.events, - eventHandle = elemData.handle; - - if ( !events ) { - elemData.events = events = {}; - } - - 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.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // 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 the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have 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, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData.events; - - if ( !elemData || !events ) { - return; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, 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 ) { - // Event object or event type - var type = event.type || event, - namespaces = [], - exclusive; - - 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.exclusive = exclusive; - event.namespace = namespaces.join("."); - event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - - // triggerHandler() and global events don't bubble or run the default action - if ( onlyHandlers || !elem ) { - event.preventDefault(); - event.stopPropagation(); - } - - // Handle a global trigger - if ( !elem ) { - // TODO: Stop taunting the data cache; remove global events and always attach to document - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - return; - } - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - event.target = elem; - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - var cur = elem, - // IE doesn't like method names with a colon (#3533, #8272) - ontype = type.indexOf(":") < 0 ? "on" + type : ""; - - // Fire event on the current element, then bubble up the DOM tree - do { - var handle = jQuery._data( cur, "handle" ); - - event.currentTarget = cur; - if ( handle ) { - handle.apply( cur, data ); - } - - // Trigger an inline bound script - if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { - event.result = false; - event.preventDefault(); - } - - // Bubble up to document, then to window - cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; - } while ( cur && !event.isPropagationStopped() ); - - // If nobody prevented the default action, do it now - if ( !event.isDefaultPrevented() ) { - var old, - special = jQuery.event.special[ type ] || {}; - - if ( (!special._default || special._default.call( elem.ownerDocument, event ) === 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. - // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. - try { - if ( ontype && elem[ type ] ) { - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - jQuery.event.triggered = type; - elem[ type ](); - } - } catch ( ieError ) {} - - if ( old ) { - elem[ ontype ] = old; - } - - jQuery.event.triggered = undefined; - } - } - - return event.result; - }, - - handle: function( event ) { - event = jQuery.event.fix( event || window.event ); - // Snapshot the handlers list since a called handler may add/remove events. - var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), - run_all = !event.exclusive && !event.namespace, - args = Array.prototype.slice.call( arguments, 0 ); - - // Use the fix-ed Event rather than the (read-only) native event - args[0] = event; - event.currentTarget = this; - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Triggered event must 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event. - if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var eventDocument = event.target.ownerDocument || document, - doc = eventDocument.documentElement, - body = eventDocument.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - 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; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - 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 ); - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.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 -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - - // set the correct event type - event.type = event.data; - - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { - - // Chrome does something similar, the parentNode property - // can be accessed but is null. - if ( parent && parent !== document && !parent.parentNode ) { - return; - } - - // Traverse up the tree - while ( parent && parent !== this ) { - parent = parent.parentNode; - } - - if ( parent !== this ) { - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( !jQuery.nodeName( this, "form" ) ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = elem.type, val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( jQuery.nodeName( elem, "select" ) ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; - - if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { - testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; - - if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - // 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. - // Don't pass args or remember liveFired; they apply to the donor event. - var event = jQuery.extend( {}, args[ 0 ] ); - event.type = type; - event.originalEvent = {}; - event.liveFired = undefined; - jQuery.event.handle.call( elem, event ); - if ( event.isDefaultPrevented() ) { - args[ 0 ].preventDefault(); - } -} - -// 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; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - - function handler( donor ) { - // Donor event is always a native one; fix it and switch its type. - // Let focusin/out handler cancel the donor focus/blur event. - var e = jQuery.event.fix( donor ); - e.type = fix; - e.originalEvent = {}; - jQuery.event.trigger( e, null, e.target ); - if ( e.isDefaultPrevented() ) { - donor.preventDefault(); - } - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - var handler; - - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( arguments.length === 2 || data === false ) { - fn = data; - data = undefined; - } - - if ( name === "one" ) { - handler = function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }; - handler.guid = fn.guid || jQuery.guid++; - } else { - handler = fn; - } - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - 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 ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( name === "die" && !types && - origSelector && origSelector.charAt(0) === "." ) { - - context.unbind( origSelector ); - - return this; - } - - if ( data === false || jQuery.isFunction( data ) ) { - fn = data || returnFalse; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( liveMap[ type ] ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, "events" ); - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - - // Make sure not to accidentally match a child element with the same selector - if ( related && jQuery.contains( elem, related ) ) { - related = elem; - } - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); -} - -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").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.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - 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 !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // 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" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - 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; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = 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 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

      "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // 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[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // 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 - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, 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, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
      "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -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 : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // 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 self = this, - i, l; - - 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; - } - } - }); - } - - var ret = this.pushStack( "", "find", selector ), - length, n, r; - - 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 targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; 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" ? - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - // Array - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[ selector ] ) { - matches[ selector ] = POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[ selector ]; - - if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - // String - var pos = POS.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { - break; - } - } - } - } - - 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 ) { - if ( !elem || typeof elem === "string" ) { - return jQuery.inArray( this[0], - // If it receives a string, the selector is used - // If it receives nothing, the siblings are used - elem ? jQuery( elem ) : this.parent().children() ); - } - // 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 ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// 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; -} - -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 jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "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.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - 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 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.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; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - 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; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
      ", "
      " ], - thead: [ 1, "", "
      " ], - tr: [ 2, "", "
      " ], - td: [ 3, "", "
      " ], - col: [ 2, "", "
      " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and