From 95863ad618faf5c96460aa4c1ee66d2882432ec3 Mon Sep 17 00:00:00 2001 From: Kevin Jump Date: Tue, 16 Feb 2016 11:36:56 +0000 Subject: [PATCH 01/78] Stylesheet RegEx to capture multi class properties Change the RegEx in Stylesheet Helper to capture mutli element classes as stylesheet properties (See U4-7160) Previously single class names "H1", "P", ".test" all work but multi ".btn btn-default" fail - this change fixes that --- src/Umbraco.Core/Strings/Css/StylesheetHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs index ff7591c6b5..afcbf5fa3f 100644 --- a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs +++ b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Strings.Css { internal class StylesheetHelper { - private const string RuleRegexFormat = @"/\*\*\s*umb_name:\s*(?{0}?)\s*\*/\s*(?[^\s,{{]*?)\s*{{\s*(?.*?)\s*}}"; + private const string RuleRegexFormat = @"/\*\*\s*umb_name:\s*(?{0}?)\s*\*/\s*(?[^,{{]*?)\s*{{\s*(?.*?)\s*}}"; public static IEnumerable ParseRules(string input) { From 3ce2b0e6a02544b2b56a4d852409636f4a302617 Mon Sep 17 00:00:00 2001 From: James Coxhead Date: Tue, 16 Feb 2016 14:06:08 +0000 Subject: [PATCH 02/78] Updated database installer to use new media picker instead of legacy picker --- .../Persistence/Migrations/Initial/BaseDataCreation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 5e07a617d4..038c1c3c1c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -237,7 +237,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, PropertyEditorAlias = Constants.PropertyEditors.ContentPickerAlias, DbType = "Integer" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, PropertyEditorAlias = Constants.PropertyEditors.MediaPickerAlias, DbType = "Integer" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Integer" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, PropertyEditorAlias = Constants.PropertyEditors.MemberPickerAlias, DbType = "Integer" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = 1040, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "Ntext" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" }); From b72d52bf90bac1ed1aa4babdc44ed1756af6bc97 Mon Sep 17 00:00:00 2001 From: Lesley Date: Thu, 18 Feb 2016 17:16:01 +0000 Subject: [PATCH 03/78] Fix U4-8029 The div was too wide so description text was unreadable. --- .../src/views/propertyeditors/grid/grid.prevalues.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html index 3061f01c29..9d9626694a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html @@ -1,5 +1,5 @@
-
+

From 64ad8f660f98d9cb25042511f29481d1e27d5f49 Mon Sep 17 00:00:00 2001 From: AndyButland Date: Sat, 12 Mar 2016 19:17:51 +0100 Subject: [PATCH 04/78] Fixed issue with misasigned task assignee on send to translation --- src/umbraco.cms/businesslogic/task/Task.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/umbraco.cms/businesslogic/task/Task.cs b/src/umbraco.cms/businesslogic/task/Task.cs index 678cd60225..294077370f 100644 --- a/src/umbraco.cms/businesslogic/task/Task.cs +++ b/src/umbraco.cms/businesslogic/task/Task.cs @@ -131,7 +131,7 @@ namespace umbraco.cms.businesslogic.task set { _user = value; - TaskEntity.OwnerUserId = _user.Id; + TaskEntity.AssigneeUserId = _user.Id; } } From e3411f7212b27b58aa7dcbf81c92f58920543088 Mon Sep 17 00:00:00 2001 From: AndyButland Date: Sat, 12 Mar 2016 19:26:45 +0100 Subject: [PATCH 05/78] Provided a check that a language was selected when sending to translation such that a message is returned to the user rather than an unexpected error --- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 1 + .../umbraco/config/lang/en_us.xml | 1 + .../umbraco/dialogs/sendToTranslation.aspx.cs | 34 ++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 0842755da3..55df243b81 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -1145,6 +1145,7 @@ To manage your website, simply open the Umbraco back office and start adding con To close a translation task, please go to the Details view and click the "Close" button. ]]> The page '%0%' has been send to translation + Please select the language that the content should be translated into Send the page '%0%' to translation Assigned by Task opened diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index ce25e990c8..2b06337be7 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -1149,6 +1149,7 @@ To manage your website, simply open the Umbraco back office and start adding con To close a translation task, please go to the Details view and click the "Close" button. ]]> The page '%0%' has been send to translation + Please select the language that the content should be translated into Send the page '%0%' to translation Assigned by Task opened diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs index 80118b4836..c02baaaa7b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sendToTranslation.aspx.cs @@ -92,20 +92,30 @@ namespace umbraco.presentation.dialogs protected void doTranslation_Click(object sender, EventArgs e) { - // testing translate - cms.businesslogic.translation.Translation.MakeNew( - _currentPage, - getUser(), - BusinessLogic.User.GetUser(int.Parse(translator.SelectedValue)), - new cms.businesslogic.language.Language(int.Parse(language.SelectedValue)), - comment.Text, includeSubpages.Checked, - true); + int languageId; + if (int.TryParse(language.SelectedValue, out languageId)) + { + cms.businesslogic.translation.Translation.MakeNew( + _currentPage, + getUser(), + BusinessLogic.User.GetUser(int.Parse(translator.SelectedValue)), + new cms.businesslogic.language.Language(languageId), + comment.Text, includeSubpages.Checked, + true); - pane_form.Visible = false; - pl_buttons.Visible = false; + pane_form.Visible = false; + pl_buttons.Visible = false; - feedback.Text = ui.Text("translation","pageHasBeenSendToTranslation", _currentPage.Text, base.getUser()) + "

" + ui.Text("defaultdialogs", "closeThisWindow") + "

"; - feedback.type = uicontrols.Feedback.feedbacktype.success; + feedback.Text = ui.Text("translation", "pageHasBeenSendToTranslation", _currentPage.Text, base.getUser()) + + "

" + + ui.Text("defaultdialogs", "closeThisWindow") + "

"; + feedback.type = uicontrols.Feedback.feedbacktype.success; + } + else + { + feedback.Text = ui.Text("translation", "noLanguageSelected"); + feedback.type = uicontrols.Feedback.feedbacktype.error; + } } } } From 233e3d9387f2022f524fd981cb74e9fa1fb1e029 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sun, 27 Mar 2016 19:07:09 +0200 Subject: [PATCH 06/78] Fix issues with tree icons + legacy icons --- .../components/tree/umbtreeitem.directive.js | 11 +++++------ src/Umbraco.Web.UI.Client/src/less/hacks.less | 8 ++++++-- src/Umbraco.Web.UI.Client/src/less/tree.less | 19 +++++++++++++------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js index 20fdc6e332..f4fe0db4e6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js @@ -34,7 +34,7 @@ angular.module("umbraco.directives") //TODO: Remove more of the binding from this template and move the DOM manipulation to be manually done in the link function, // this will greatly improve performance since there's potentially a lot of nodes being rendered = a LOT of watches! - template: '
  • ' + + template: '
  • ' + '
    ' + //NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog //'' + @@ -72,14 +72,13 @@ angular.module("umbraco.directives") //set the padding .css("padding-left", (node.level * 20) + "px"); - //remove first 'ins' if there is no children - //show/hide last 'ins' depending on children + //toggle visibility of last 'ins' depending on children + //visibility still ensure the space is "reserved", so both nodes with and without children are aligned. if (!node.hasChildren) { - element.find("ins:first").remove(); - element.find("ins").last().hide(); + element.find("ins").last().css("visibility", "hidden"); } else { - element.find("ins").last().show(); + element.find("ins").last().css("visibility", "visible"); } var icon = element.find("i:first"); diff --git a/src/Umbraco.Web.UI.Client/src/less/hacks.less b/src/Umbraco.Web.UI.Client/src/less/hacks.less index 0d41eed050..fb809af015 100644 --- a/src/Umbraco.Web.UI.Client/src/less/hacks.less +++ b/src/Umbraco.Web.UI.Client/src/less/hacks.less @@ -63,9 +63,13 @@ iframe, .content-column-body { /*tree legacy icon*/ -.legacy-custom-file{ - width: 16px; height: 16px; margin-right: 11px; display: inline-block; +.legacy-custom-file { + width: 16px; + height: 16px; + min-width: 20px; /* this ensure the icon takes up same space as font-icon (20px) */ + display: inline-block; background-position: center center; + background-repeat: no-repeat; } /* diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index 185b5a6e3b..61286c05a9 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -155,6 +155,11 @@ display: flex; } +.umb-tree li > div:hover a:not(.umb-options) { + overflow: hidden; + margin-right: 6px; +} + .umb-tree .icon { vertical-align: middle; margin: 0 13px 0 0; @@ -477,7 +482,6 @@ div.locked:before{ width:100%; height:1px; overflow:hidden; - position: absolute; left: 0; bottom: 0; @@ -495,15 +499,18 @@ div.locked:before{ /*body.touch .umb-tree .icon{font-size: 19px;}*/ body.touch .umb-tree ins{font-size: 14px; visibility: visible; padding: 7px;} -body.touch .umb-tree li div { +body.touch .umb-tree li > div { padding-top: 8px; padding-bottom: 8px; font-size: 110%; } -body.touch .umb-actions a{ - padding: 7px 25px 7px 20px; - font-size: 110%; +// change height of this if touch devices should have a different height of preloader. +body.touch .umb-tree li div.l div { + padding: 0; } -body.touch a.umb-options i {margin-top: 20px;} +body.touch .umb-actions a { + padding: 7px 25px 7px 20px; + font-size: 110%; +} \ No newline at end of file From 0c9dcc1f5ad65b761588b889795b7b524653f906 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Mon, 28 Mar 2016 01:47:01 +0200 Subject: [PATCH 07/78] Fix errors when saving document type when no icon is selected. --- .../editor/umbeditorheader.directive.js | 23 ++++++++++++------- .../src/common/services/iconhelper.service.js | 13 +++++++++-- .../common/dialogs/iconpicker.controller.js | 11 +++++---- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js index 1f12164b18..cc57eb6e74 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js @@ -212,15 +212,22 @@ Use this directive to construct a header inside the main editor window. scope.dialogModel = { view: "iconpicker", show: true, - submit: function(model) { - if (model.color) { - scope.icon = model.icon + " " + model.color; - } else { - scope.icon = model.icon; - } + submit: function (model) { - // set form to dirty - ctrl.$setDirty(); + /* ensure an icon is selected, because on focus on close button + or an element in background no icon is submitted. So don't clear/update existing icon/preview. + */ + if (model.icon) { + + if (model.color) { + scope.icon = model.icon + " " + model.color; + } else { + scope.icon = model.icon; + } + + // set form to dirty + ctrl.$setDirty(); + } scope.dialogModel.show = false; scope.dialogModel = null; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js index 6d83c1b907..04194838ab 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js @@ -109,11 +109,16 @@ function iconHelper($q, $timeout) { }, formatContentTypeIcons: function (contentTypes) { for (var i = 0; i < contentTypes.length; i++) { - contentTypes[i].icon = this.convertFromLegacyIcon(contentTypes[i].icon); + if (!contentTypes[i].icon) { + //just to be safe (e.g. when focus was on close link and hitting save) + contentTypes[i].icon = "icon-document"; // default icon + } else { + contentTypes[i].icon = this.convertFromLegacyIcon(contentTypes[i].icon); + } //couldnt find replacement if(contentTypes[i].icon.indexOf(".") > 0){ - contentTypes[i].icon = "icon-document-dashed-line"; + contentTypes[i].icon = "icon-document-dashed-line"; } } return contentTypes; @@ -128,6 +133,10 @@ function iconHelper($q, $timeout) { }, /** If the icon is legacy */ isLegacyIcon: function (icon) { + if(!icon) { + return false; + } + if(icon.startsWith('..')){ return false; } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.controller.js index de71977ebe..ec1ad6e663 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.controller.js @@ -7,13 +7,14 @@ angular.module("umbraco") $scope.icons = icons; }); - $scope.submitClass = function(icon){ - if($scope.color) - { + $scope.submitClass = function (icon) { + if($scope.color) { $scope.submit(icon + " " + $scope.color); - }else{ - $scope.submit(icon); + } + else { + $scope.submit(icon); } }; + } ); \ No newline at end of file From 30e9a1ef82549c15493fbf791ae2305d9c9de948 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Mon, 28 Mar 2016 02:29:03 +0200 Subject: [PATCH 08/78] Don't set dirty when just filtering icons. --- .../src/views/common/dialogs/iconpicker.html | 5 +++-- .../src/views/common/overlays/iconpicker/iconpicker.html | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html index 260d8ff85c..96ab990447 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html @@ -4,10 +4,11 @@
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/iconpicker/iconpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/iconpicker/iconpicker.html index 83a02a4504..0091289e6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/iconpicker/iconpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/iconpicker/iconpicker.html @@ -9,7 +9,8 @@ class="umb-search-field search-query input-block-level" localize="placeholder" placeholder="@placeholders_filter" - umb-auto-focus> + umb-auto-focus + no-dirty-check>
    From ae913ede6f03e62d92f60e9d4dbaf4d78bd38520 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Sun, 10 Apr 2016 00:07:03 +0200 Subject: [PATCH 09/78] Virtualized creating of application context Closed setting up of application context Opens up a whole bunch of doors. :) --- .../Routing/UrlRoutingTestBase.cs | 4 +- .../TestHelpers/BaseDatabaseFactoryTest.cs | 45 ++++++++++--------- .../TestHelpers/BaseUmbracoApplicationTest.cs | 13 ++++-- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 475909318a..be9928004b 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -57,10 +57,10 @@ namespace Umbraco.Tests.Routing public const int LangNlId = 337; public const int LangDkId = 338; - protected override void SetupApplicationContext() + protected override ApplicationContext CreateApplicationContext() { var settings = SettingsForTests.GetDefault(); - ApplicationContext.Current = new ApplicationContext( + return new ApplicationContext( new DatabaseContext(Mock.Of(), Logger, Mock.Of(), "test"), GetServiceContext(settings, Logger), CacheHelper, diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index 967998e517..d24a411f73 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -57,6 +57,7 @@ namespace Umbraco.Tests.TestHelpers private string _dbPath; //used to store (globally) the pre-built db with schema and initial data private static Byte[] _dbBytes; + private DefaultDatabaseFactory dbFactory; [SetUp] public override void Initialize() @@ -66,27 +67,11 @@ namespace Umbraco.Tests.TestHelpers var path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", path); - //disable cache - var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); - - var dbFactory = new DefaultDatabaseFactory( + dbFactory = new DefaultDatabaseFactory( GetDbConnectionString(), GetDbProviderName(), Logger); - var repositoryFactory = new RepositoryFactory(cacheHelper, Logger, SqlSyntax, SettingsForTests.GenerateMockSettings()); - - var evtMsgs = new TransientMessagesFactory(); - _appContext = new ApplicationContext( - //assign the db context - new DatabaseContext(dbFactory, Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), - //assign the service context - new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), cacheHelper, Logger, evtMsgs), - cacheHelper, - ProfilingLogger) - { - IsReady = true - }; base.Initialize(); @@ -103,16 +88,32 @@ namespace Umbraco.Tests.TestHelpers } } + protected override ApplicationContext CreateApplicationContext() + { + //disable cache + var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); + + var repositoryFactory = new RepositoryFactory(cacheHelper, Logger, SqlSyntax, SettingsForTests.GenerateMockSettings()); + + var evtMsgs = new TransientMessagesFactory(); + _appContext = new ApplicationContext( + //assign the db context + new DatabaseContext(dbFactory, Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), + //assign the service context + new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), cacheHelper, Logger, evtMsgs), + cacheHelper, + ProfilingLogger) + { + IsReady = true + }; + return _appContext; + } + protected virtual ISqlSyntaxProvider SqlSyntax { get { return new SqlCeSyntaxProvider(); } } - protected override void SetupApplicationContext() - { - ApplicationContext.Current = _appContext; - } - /// /// The database behavior to use for the test/fixture /// diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index abf1edd3a5..83020fd386 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -147,17 +147,21 @@ namespace Umbraco.Tests.TestHelpers /// /// Inheritors can override this if they wish to create a custom application context /// - protected virtual void SetupApplicationContext() + protected void SetupApplicationContext() { + var applicationContext = CreateApplicationContext(); + ApplicationContext.Current = applicationContext; + } + protected virtual ApplicationContext CreateApplicationContext() + { var sqlSyntax = new SqlCeSyntaxProvider(); var repoFactory = new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), Logger, sqlSyntax, SettingsForTests.GenerateMockSettings()); var evtMsgs = new TransientMessagesFactory(); - ApplicationContext.Current = new ApplicationContext( + var applicationContext = new ApplicationContext( //assign the db context - new DatabaseContext(new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, Logger), - Logger, sqlSyntax, "System.Data.SqlServerCe.4.0"), + new DatabaseContext(new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, Logger), Logger, sqlSyntax, "System.Data.SqlServerCe.4.0"), //assign the service context new ServiceContext(repoFactory, new PetaPocoUnitOfWorkProvider(Logger), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), CacheHelper, Logger, evtMsgs), CacheHelper, @@ -165,6 +169,7 @@ namespace Umbraco.Tests.TestHelpers { IsReady = true }; + return applicationContext; } /// From 054fd9ecef0fc94a7b327bbd34d1d87cbd4f059f Mon Sep 17 00:00:00 2001 From: bjarnef Date: Thu, 14 Apr 2016 22:18:14 +0200 Subject: [PATCH 10/78] Fix line-height when using custom icon font as section icon. --- src/Umbraco.Web.UI.Client/src/less/sections.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/sections.less b/src/Umbraco.Web.UI.Client/src/less/sections.less index c2db58a99e..c89be83a10 100644 --- a/src/Umbraco.Web.UI.Client/src/less/sections.less +++ b/src/Umbraco.Web.UI.Client/src/less/sections.less @@ -22,6 +22,8 @@ ul.sections li [class^="icon-"]:before, ul.sections li [class*=" icon-"]:before, ul.sections li img.icon-section { font-size: 30px; + line-height: 20px; /* set line-height to ensure all icons use same line-height */ + display: inline-block; margin: 1px 0 0 0; opacity: 0.4; -webkit-transition: all .3s linear; From e9bf41e869157b05cfdb4e3a6f0a39e3f72b55cd Mon Sep 17 00:00:00 2001 From: bjarnef Date: Thu, 14 Apr 2016 23:22:26 +0200 Subject: [PATCH 11/78] Wrap text "Include all child nodes" in a label --- src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx index 82746bb7c2..edea60c62b 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx @@ -75,7 +75,7 @@
    - Include all child nodes + From 1d428045b6e65dbb62040a8c0499f0349453d0e1 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Mon, 18 Apr 2016 15:35:09 +0200 Subject: [PATCH 12/78] Don't remove virtual on SetupApplicationContext. Might be many external inheritors. --- src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index 83020fd386..84b109a66a 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -147,7 +147,7 @@ namespace Umbraco.Tests.TestHelpers /// /// Inheritors can override this if they wish to create a custom application context /// - protected void SetupApplicationContext() + protected virtual void SetupApplicationContext() { var applicationContext = CreateApplicationContext(); ApplicationContext.Current = applicationContext; From 3564e702594385770c553bd13dd4a8354f1013e2 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Mon, 18 Apr 2016 20:42:19 +0200 Subject: [PATCH 13/78] Localize "unsaved changes" dialog. --- .../views/common/notifications/confirmroutechange.html | 10 +++++----- src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml | 6 ++++++ src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/de.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/es.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/fr.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/he.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/it.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/ja.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/ko.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/nl.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/pl.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/pt.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/ru.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/sv.xml | 6 ++++++ src/Umbraco.Web.UI/umbraco/config/lang/zh.xml | 6 ++++++ 19 files changed, 113 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.html b/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.html index 80942baaeb..c3b72f67a8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/notifications/confirmroutechange.html @@ -1,7 +1,7 @@
    -

    You have unsaved changes

    -

    Are you sure you want to navigate away from this page? - you have unsaved changes

    +

    You have unsaved changes

    +

    Are you sure you want to navigate away from this page? - you have unsaved changes

    - - -
    + + +
    \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml index 62aeb85cc0..7d6c52ad9b 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml @@ -179,6 +179,12 @@ Navštívit Vítejte + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Název Spravovat názvy hostitelů diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml index a02fa21219..47bf684818 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml @@ -186,6 +186,12 @@ Besøk Velkommen + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Navn på lokal link Rediger domener diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index 446796dd88..4c3dcc749f 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -187,6 +187,12 @@ Besøg Velkommen + + Bliv + Kassér ændringer + Du har ikke-gemte ændringer + Er du sikker på du vil navigere væk fra denne side? - du har ikke-gemte ændringer + Navn på lokalt link Rediger domæner diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml index 1dab89a922..a3f40cc0ea 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml @@ -186,6 +186,12 @@ Besuchen Willkommen + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Name Hostnamen verwalten diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index b810183d42..7b476e5e8b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -197,6 +197,12 @@ Visit Welcome + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Name Manage hostnames diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 402902f48c..534185e5db 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -199,6 +199,12 @@ Visit Welcome + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Name Manage hostnames diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml index c1478abbb1..9e79db1efa 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml @@ -185,6 +185,12 @@ Visita Bienvenido + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Nombre Administrar dominios diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml index a0842c8821..45153d78fa 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml @@ -181,6 +181,12 @@ Visiter Bienvenue + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Name Gérer les noms d'hôtes diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml index 4b006e8524..fab17bb6a4 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/he.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/he.xml @@ -131,6 +131,12 @@ בקר ברוכים הבאים + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + שם ניהול שם מתחם diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml index d07d0cb049..7c26a2538a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/it.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/it.xml @@ -127,6 +127,12 @@ Visita Benvenuto + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Nome Gestione alias Hostnames diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml index e1b675b208..177e9d6aa5 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ja.xml @@ -194,6 +194,12 @@ 訪れる ようこそ + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + 名前 ドメインの割り当て diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml index ee8db9901c..db0aa62d11 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ko.xml @@ -125,6 +125,12 @@ 방문 환영합니다 + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + 이름 호스트네임 관리 diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml index 9c8f587ca2..9fb6f51402 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml @@ -188,6 +188,12 @@ Bezoek Welkom + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Naam Beheer domeinnamen diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml index 3c24885eb3..1a3058e289 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pl.xml @@ -125,6 +125,12 @@ Odwiedź Witaj + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Nazwa Zarządzaj nazwami hostów diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml index 4c039524ab..736bb7a507 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/pt.xml @@ -125,6 +125,12 @@ Visitar Bem Vindo(a) + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Nome Gerenciar hostnames diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml index fbf0e0adf2..8f039dcc71 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml @@ -254,6 +254,12 @@ Посетить Рады приветствовать + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Название Управление доменами diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml index b620ecc168..c397c735b3 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml @@ -181,6 +181,12 @@ Välkommen Besök + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + Namn Hantera domännamn diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml index 6237bb4f07..69f938c42d 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml @@ -166,6 +166,12 @@ 访问 欢迎 + + Stay + Discard changes + You have unsaved changes + Are you sure you want to navigate away from this page? - you have unsaved changes + 锚点名称 管理主机名 From 9174029126cf6ddabf8337c777e0a89487b53c94 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Mon, 18 Apr 2016 22:33:38 +0200 Subject: [PATCH 14/78] Fix localization of listview buttons/links actions. --- .../views/propertyeditors/listview/listview.html | 15 ++++++++------- src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 11 ++++++++--- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 5 +++-- src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 3 ++- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 904939b75f..64c8e6216d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -31,13 +31,14 @@ - {{ selectedItemsCount() }} of {{ listViewResultSet.items.length }} selected + {{ selectedItemsCount() }} of {{ listViewResultSet.items.length }} selected
    @@ -86,7 +87,7 @@ type="button" button-style="link" label="Publish" - key="actions_publish" + label-key="actions_publish" icon="icon-globe" action="publish()" disabled="actionInProgress"> @@ -97,7 +98,7 @@ type="button" button-style="link" label="Unpublish" - key="actions_unpublish" + label-key="actions_unpublish" icon="icon-block" action="unpublish()" disabled="actionInProgress"> @@ -108,7 +109,7 @@ type="button" button-style="link" label="Copy" - key="actions_copy" + label-key="actions_copy" icon="icon-documents" action="copy()" disabled="actionInProgress"> @@ -119,7 +120,7 @@ type="button" button-style="link" label="Move" - key="actions_move" + label-key="actions_move" icon="icon-enter" action="move()" disabled="actionInProgress"> @@ -129,8 +130,8 @@ ng-if="options.allowBulkDelete && (buttonPermissions == null || buttonPermissions.canDelete)" type="button" button-style="link" - label="Delete" - key="actions_delete" + label="Delete" + label-key="actions_delete" icon="icon-trash" action="delete()" disabled="actionInProgress"> diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index 446796dd88..e9631c0e93 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -60,6 +60,7 @@ For + Ryd valg Vælg Vælg nuværende mappe Gør noget andet @@ -165,6 +166,10 @@ Klik for at uploade Slip filerne her... + Link til medie + eller klik her for at vælge filer + Tilladte filtyper er kun + Maks filstørrelse er Opret et nyt medlem @@ -197,7 +202,7 @@ Er du sikker på at du vil forlade Umbraco? Er du sikker? Klip - Rediger ordbogs nøgle + Rediger ordbogsnøgle Rediger sprog Indsæt lokalt link Indsæt tegn @@ -421,8 +426,8 @@ Listevisning Gemmer... nuværende - Flyt Indlejring + valgt @@ -985,7 +990,7 @@ Mange hilsner fra Umbraco robotten Roller Medlemstype Dokumenttyper - Dokumenttyper + Relationstyper Pakker Pakker diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index b810183d42..ad0891a616 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -65,6 +65,7 @@ Viewing for + Clear selection Select Select current folder Do something else @@ -171,7 +172,7 @@ Click to upload Drop your files here... - Link to media + Link to media or click here to choose files Only allowed file types are Max file size is @@ -479,8 +480,8 @@ List view Saving... current - Move Embed + selected diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 402902f48c..bb4e1b0e7a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -65,6 +65,7 @@ Viewing for + Clear selection Select Select current folder Do something else @@ -483,8 +484,8 @@ List view Saving... current - Move Embed + selected Black From 72cef006d38307a7b43aa5035dcf5546f9c85a42 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 20 Apr 2016 15:56:06 +0200 Subject: [PATCH 15/78] bumps version --- build/UmbracoVersion.txt | 2 +- src/SolutionInfo.cs | 4 ++-- src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/UmbracoVersion.txt b/build/UmbracoVersion.txt index 4cecf0bd3e..4b66ecc866 100644 --- a/build/UmbracoVersion.txt +++ b/build/UmbracoVersion.txt @@ -1,2 +1,2 @@ # Usage: on line 2 put the release version, on line 3 put the version comment (example: beta) -7.4.3 \ No newline at end of file +7.5.0 \ No newline at end of file diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index bcbd95ecd1..caeb303f68 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -11,5 +11,5 @@ using System.Resources; [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("7.4.3")] -[assembly: AssemblyInformationalVersion("7.4.3")] \ No newline at end of file +[assembly: AssemblyFileVersion("7.5.0")] +[assembly: AssemblyInformationalVersion("7.5.0")] \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index d19e020a91..762d3da59c 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration { public class UmbracoVersion { - private static readonly Version Version = new Version("7.4.3"); + private static readonly Version Version = new Version("7.5.0"); /// /// Gets the current version of Umbraco. diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 2f48f4a2e3..33d150490b 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -2243,7 +2243,7 @@ Form - + @@ -2414,9 +2414,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" True True - 7430 + 7500 / - http://localhost:7430 + http://localhost:7500 False False From 7e13781d8b3e6095b203e9497cf69caaafaa4bb0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 20 Apr 2016 16:04:35 +0200 Subject: [PATCH 16/78] fixes merge issue --- src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml | 3 ++- src/Umbraco.Web.UI/config/ClientDependency.config | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml index 3d4f6baa7e..eb09f333e3 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml @@ -64,7 +64,8 @@ diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index 80d8db2da3..72cb97f698 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - + integer, the above tryparse will fail. So we'll try going + // via decimal too to return the integer value rather than zero. + decimal decimalForIntegerValue; + if (decimal.TryParse(stringValue, out decimalForIntegerValue)) + { + integerValue = (int)decimalForIntegerValue; + } + } + + value = integerValue; + break; + case DataTypeDatabaseType.Decimal: + decimal decimalValue; + decimal.TryParse(stringValue, out decimalValue); + value = decimalValue; + break; + case DataTypeDatabaseType.Date: + DateTime dateValue; + DateTime.TryParse(stringValue, out dateValue); + value = dateValue; + break; + } + } + else + { + throw new Exception( + string.Format( + "Type validation failed. The value type: '{0}' does not match the DataType in PropertyType with alias: '{1}'", + value == null ? "null" : value.GetType().Name, Alias)); + } + } SetPropertyValueAndDetectChanges(o => { diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 0649801a0c..00e7fc8d13 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Text.RegularExpressions; @@ -425,6 +426,19 @@ namespace Umbraco.Core.Models return false; } + /// + /// Checks the underlying property editor prevalues to see if the one that allows changing of the database field + /// to which data is saved (dataInt, dataVarchar etc.) is included. If so that means the field could be changed when the data + /// type is saved. + /// + /// + internal bool CanHaveDataValueTypeChanged() + { + var propertyEditor = PropertyEditorResolver.Current.GetByAlias(_propertyEditorAlias); + return propertyEditor.PreValueEditor.Fields + .SingleOrDefault(x => x.Key == Constants.PropertyEditors.DataValueTypePreValueKey) != null; + } + /// /// Validates the Value from a Property according to the validation settings /// diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs index eb08b07d43..a7154d7d67 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs @@ -130,20 +130,20 @@ namespace Umbraco.Core.PropertyEditors { switch (ValueType.ToUpper(CultureInfo.InvariantCulture)) { - case "INT": - case "INTEGER": + case PropertyEditorValueTypes.IntegerType: + case PropertyEditorValueTypes.IntegerTypeAlternative: return DataTypeDatabaseType.Integer; - case "DECIMAL": + case PropertyEditorValueTypes.DecimalType: return DataTypeDatabaseType.Decimal; - case "STRING": + case PropertyEditorValueTypes.StringType: return DataTypeDatabaseType.Nvarchar; - case "TEXT": - case "JSON": - case "XML": + case PropertyEditorValueTypes.TextType: + case PropertyEditorValueTypes.JsonType: + case PropertyEditorValueTypes.XmlType: return DataTypeDatabaseType.Ntext; - case "DATETIME": - case "DATE": - case "TIME": + case PropertyEditorValueTypes.DateTimeType: + case PropertyEditorValueTypes.DateType: + case PropertyEditorValueTypes.TimeType: return DataTypeDatabaseType.Date; default: throw new FormatException("The ValueType does not match a known value type"); diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 035cfd0ab6..75234fa3ab 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -504,6 +504,8 @@ namespace Umbraco.Core.Services if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this)) return; + OverrideDatabaseTypeIfProvidedInPreValues(dataTypeDefinition, values); + var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow)) { @@ -523,6 +525,36 @@ namespace Umbraco.Core.Services Audit(AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id); } + /// + /// If the database data field is provided in the pre-values update the data type definition to that instead of the + /// default for the property editor + /// + /// + /// + private static void OverrideDatabaseTypeIfProvidedInPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values) + { + if (values != null && values.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey)) + { + switch (values[Constants.PropertyEditors.DataValueTypePreValueKey].Value) + { + case PropertyEditorValueTypes.StringType: + dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Nvarchar; + break; + case PropertyEditorValueTypes.IntegerType: + dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Integer; + break; + case PropertyEditorValueTypes.DecimalType: + dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Decimal; + break; + case PropertyEditorValueTypes.DateTimeType: + dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Date; + break; + case PropertyEditorValueTypes.TextType: + dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Ntext; + break; + } + } + } /// /// Deletes an diff --git a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs index 1132fcfacd..fab9d0bba3 100644 --- a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs @@ -41,7 +41,6 @@ namespace Umbraco.Web.PropertyEditors internal class LabelPreValueEditor : PreValueEditor { - private const string ValueTypeKey = "valueType"; private const string LegacyPropertyEditorValuesKey = "values"; public LabelPreValueEditor() @@ -56,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors ValueType = PropertyEditorValueTypes.StringType; } - [PreValueField(ValueTypeKey, "Value type", "valuetype")] + [PreValueField(Constants.PropertyEditors.DataValueTypePreValueKey, "Value type", "valuetype")] public string ValueType { get; set; } /// @@ -72,19 +71,19 @@ namespace Umbraco.Web.PropertyEditors // Check for a saved value type. If not found set to default string type. var valueType = PropertyEditorValueTypes.StringType; - if (existing.ContainsKey(ValueTypeKey)) + if (existing.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey)) { - valueType = (string)existing[ValueTypeKey]; + valueType = (string)existing[Constants.PropertyEditors.DataValueTypePreValueKey]; } // Convert any other values from a legacy property editor to a list, easier to enumerate on the editor. // Make sure to exclude values defined on the label property editor itself. var asList = existing .Select(e => new KeyValuePair(e.Key, e.Value)) - .Where(e => e.Key != ValueTypeKey) + .Where(e => e.Key != Constants.PropertyEditors.DataValueTypePreValueKey) .ToList(); - var result = new Dictionary { { ValueTypeKey, valueType } }; + var result = new Dictionary { { Constants.PropertyEditors.DataValueTypePreValueKey, valueType } }; if (asList.Any()) { result.Add("values", asList); From 271f4e7a4a60ddd75ddb3b0c7eef5ef88d7db84d Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 10 May 2016 12:29:13 +0200 Subject: [PATCH 36/78] U4-8413 - fix missing ServersLock object --- src/Umbraco.Core/Constants-ObjectTypes.cs | 5 +- .../Migrations/Initial/BaseDataCreation.cs | 7 ++- .../EnsureServersLockObject.cs | 54 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../config/ClientDependency.config | 2 +- .../config/umbracoSettings.config | 2 + 6 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs diff --git a/src/Umbraco.Core/Constants-ObjectTypes.cs b/src/Umbraco.Core/Constants-ObjectTypes.cs index 560cd4b306..7ec45db7be 100644 --- a/src/Umbraco.Core/Constants-ObjectTypes.cs +++ b/src/Umbraco.Core/Constants-ObjectTypes.cs @@ -143,7 +143,10 @@ namespace Umbraco.Core /// public const string LockObject = "87A9F1FF-B1E4-4A25-BABB-465A4A47EC41"; - + /// + /// Guid for a Lock object. + /// + public static readonly Guid LockObjectGuid = new Guid(LockObject); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index fa3c60ffa1..8046de454b 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -134,13 +134,16 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1045, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1045", SortOrder = 2, UniqueId = new Guid("7E3962CC-CE20-4FFC-B661-5897A894BA7E"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - + //TODO: We're not creating these for 7.0 //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1039, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1039", SortOrder = 2, UniqueId = new Guid("06f349a9-c949-4b6a-8660-59c10451af42"), Text = "Ultimate Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1038, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1038", SortOrder = 2, UniqueId = new Guid("1251c96c-185c-4e9b-93f4-b48205573cbd"), Text = "Simple Editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - + //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1042, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1042", SortOrder = 2, UniqueId = new Guid("0a452bd5-83f9-4bc3-8403-1286e13fb77e"), Text = "Macro Container", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + + // all lock objects + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.ServersLock, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1," + Constants.System.ServersLock, SortOrder = 1, UniqueId = new Guid("0AF5E610-A310-4B6F-925F-E928D5416AF7"), Text = "LOCK: Servers", NodeObjectType = Constants.ObjectTypes.LockObjectGuid, CreateDate = DateTime.Now }); } private void CreateCmsContentTypeData() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs new file mode 100644 index 0000000000..6542bf4798 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs @@ -0,0 +1,54 @@ +using System; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZero +{ + [Migration("7.5.0", 10, GlobalSettings.UmbracoMigrationName)] + public class EnsureServersLockObject : MigrationBase + { + public EnsureServersLockObject(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { } + + public override void Up() + { + // that lock object should have been part of BaseDataCreation since 7.3.0 but + // for some reason it was not, so it was created during migrations but not during + // new installs, so for ppl that upgrade, make sure they have it + + EnsureLockObject(Constants.System.ServersLock, "0AF5E610-A310-4B6F-925F-E928D5416AF7", "LOCK: Servers"); + } + + public override void Down() + { + // not implemented + } + + private void EnsureLockObject(int id, string uniqueId, string text) + { + var exists = Context.Database.Exists(id); + if (exists) return; + + Insert + .IntoTable("umbracoNode") + .EnableIdentityInsert() + .Row(new + { + id = id, // NodeId + trashed = false, + parentId = -1, + nodeUser = 0, + level = 1, + path = "-1," + id, + sortOrder = 0, + uniqueId = new Guid(uniqueId), + text = text, + nodeObjectType = new Guid(Constants.ObjectTypes.LockObject), + createDate = DateTime.Now + }); + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ce34b6ef8f..2bbf4a7c7b 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -415,6 +415,7 @@ + diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index 72cb97f698..2115c540b7 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - + 1 + 1079 + 1080 From 7ae1060f504f58e9fd2e0238444e0b81c7371521 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 10 May 2016 18:25:18 +0200 Subject: [PATCH 37/78] U4-7295 Examine search with the data in the grid should be easier OOTB --- .../PropertyEditors/GridPropertyEditor.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 5228bde1a5..e69c3ae94a 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -3,15 +3,103 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Examine; +using Lucene.Net.Documents; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; +using UmbracoExamine; namespace Umbraco.Web.PropertyEditors { [PropertyEditor(Core.Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = "JSON", Group="rich content", Icon="icon-layout")] public class GridPropertyEditor : PropertyEditor { + /// + /// We're going to bind to the Examine events so we can ensure grid data is index nicely + /// + /// + /// I think this kind of logic belongs on this property editor, putting this inside of the indexer certainly doesn't seem right + /// + static GridPropertyEditor() + { + foreach (var i in ExamineManager.Instance.IndexProviderCollection.OfType()) + { + i.DocumentWriting += DocumentWriting; + } + } + + private static void DocumentWriting(object sender, Examine.LuceneEngine.DocumentWritingEventArgs e) + { + var indexer = (BaseUmbracoIndexer)sender; + foreach (var field in indexer.IndexerData.UserFields) + { + if (e.Fields.ContainsKey(field.Name)) + { + if (e.Fields[field.Name].DetectIsJson()) + { + try + { + var json = JsonConvert.DeserializeObject(e.Fields[field.Name]); + + //check if this is formatted for grid json + JToken name; + JToken sections; + if (json.HasValues && json.TryGetValue("name", out name) && json.TryGetValue("sections", out sections)) + { + //get all values and put them into a single field (using JsonPath) + var sb = new StringBuilder(); + foreach (var row in json.SelectTokens("$.sections[*].rows[*]")) + { + var rowName = row["name"].Value(); + var areaVals = row.SelectTokens("$.areas[*].controls[*].value"); + + foreach (var areaVal in areaVals) + { + var str = areaVal.Value(); + str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; + sb.Append(str); + sb.Append(" "); + + //add the row name as an individual field + e.Document.Add( + new Field( + string.Format("{0}.{1}", field.Name, rowName), str, Field.Store.YES, Field.Index.ANALYZED)); + } + } + + if (sb.Length > 0) + { + //First save the raw value to a raw field + e.Document.Add( + new Field( + string.Format("{0}{1}", UmbracoContentIndexer.RawFieldPrefix, field.Name), + e.Fields[field.Name], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO)); + + //now replace the original value with the combined/cleaned value + e.Document.RemoveField(field.Name); + e.Document.Add( + new Field( + field.Name, + sb.ToString(), Field.Store.YES, Field.Index.ANALYZED)); + } + } + } + catch (JsonException) + { + //swallow...on purpose, there's a chance that this isn't json and we don't want that to affect + // the website. + } + + } + } + } + } + /// /// Overridden to ensure that the value is validated /// From fb55b0a60b2e9f89c7c50413548603967759d7c9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 10 May 2016 18:32:32 +0200 Subject: [PATCH 38/78] U4-8371 Dont ship with the {machinename} token for Examine --- src/Umbraco.Web.UI/config/ExamineIndex.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI/config/ExamineIndex.config b/src/Umbraco.Web.UI/config/ExamineIndex.config index 7212053ca0..a853847ecb 100644 --- a/src/Umbraco.Web.UI/config/ExamineIndex.config +++ b/src/Umbraco.Web.UI/config/ExamineIndex.config @@ -9,10 +9,10 @@ More information and documentation can be found on CodePlex: http://umbracoexami - + - + @@ -25,6 +25,6 @@ More information and documentation can be found on CodePlex: http://umbracoexami - + \ No newline at end of file From 597b4c3dd280a7013a46c10f77d0504d7b446f76 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Wed, 11 May 2016 21:44:22 +0200 Subject: [PATCH 39/78] Added button to create only available doctype Hides dropdown when listViewAllowedTypes.length > 1 Shows button for single when listViewAllowedTypes.length === 1 --- .../src/views/propertyeditors/listview/listview.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 904939b75f..be31221522 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -11,7 +11,7 @@ -
    + + From 4d0dc90042600002a788657178726865a2584265 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 12 May 2016 11:16:39 +0200 Subject: [PATCH 40/78] Revert "RteMacroRenderingValueConverter should return an IHtmlString" This reverts commit 7e9a14be83fc0fd8c82f03ed27d10a387dbba5e6. --- .../ValueConverters/RteMacroRenderingValueConverter.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index d6e866e06a..2802a4d631 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { /// - /// A value converter for TinyMCE that will ensure any macro content is rendered properly even when + /// A value converter for TinyMCE that will ensure any macro content is rendered properly even when /// used dynamically. /// // because that version of RTE converter parses {locallink} and executes macros, when going from @@ -38,7 +38,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters UmbracoContext.Current.InPreviewMode = preview; var sb = new StringBuilder(); - + try { var umbracoHelper = new UmbracoHelper(UmbracoContext.Current); @@ -55,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters finally { // restore - UmbracoContext.Current.InPreviewMode = inPreviewMode; + UmbracoContext.Current.InPreviewMode = inPreviewMode; } return sb.ToString(); @@ -109,12 +109,12 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters if (modified) { - return new HtmlString(doc.DocumentNode.OuterHtml); + return doc.DocumentNode.OuterHtml; } } } - return new HtmlString(sourceString ?? string.Empty); + return sourceString; } } } \ No newline at end of file From f130e86c88210d49015827a2d2c2378346ce2d32 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 12 May 2016 12:27:02 +0200 Subject: [PATCH 41/78] U4-8448 Background task runner missing a null check during shutdown --- src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs index adb9c6c0dd..d63fbb4606 100644 --- a/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs @@ -305,7 +305,9 @@ namespace Umbraco.Web.Scheduling // tasks in the queue will be executed... if (wait == false) return; - _runningTask.Wait(); // wait for whatever is running to end... + + if (_runningTask != null) + _runningTask.Wait(); // wait for whatever is running to end... } /// From 4752a8313529b68b476ee8c28e72449cd08115dd Mon Sep 17 00:00:00 2001 From: Simon Busborg Date: Tue, 17 May 2016 11:02:01 +0200 Subject: [PATCH 42/78] Fixes: U4-8362 Inserting image in a grid with Firefox shows full-size rather than scaled image --- .../src/less/property-editors.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index a06484b8a0..96deaef09a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -201,6 +201,15 @@ ul.color-picker li a { margin: 5px; background: white; border: 1px solid #f8f8f8; + + max-width: 100%; +} + + +.umb-mediapicker .umb-sortable-thumbnails li { + flex-direction: column; + margin: 0; + padding: 5px; } @@ -384,6 +393,7 @@ ul.color-picker li a { } .umb-cropper-gravity .viewport, .umb-cropper-gravity, .umb-cropper-imageholder { display: inline-block; + max-width: 100%; } .umb-cropper-imageholder { From d826f04b548ce9e10ac34662fd478eb8e382234f Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 17 May 2016 12:17:05 +0200 Subject: [PATCH 43/78] Ensures sort order is accurate to what is in the database --- src/Umbraco.Web/umbraco.presentation/content.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/content.cs b/src/Umbraco.Web/umbraco.presentation/content.cs index bdd8c91f18..dc303c809d 100644 --- a/src/Umbraco.Web/umbraco.presentation/content.cs +++ b/src/Umbraco.Web/umbraco.presentation/content.cs @@ -528,12 +528,14 @@ where umbracoNode.id in (select cmsDocument.nodeId from cmsDocument where cmsDoc order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; XmlElement last = null; + var db = ApplicationContext.Current.DatabaseContext.Database; //NOTE: Query creates a reader - does not load all into memory foreach (var row in db.Query(sql, new { type = new Guid(Constants.ObjectTypes.Document)})) { string parentId = ((int)row.parentID).ToInvariantString(); string xml = row.xml; + int sortOrder = row.sortOrder; //if the parentid is changing if (last != null && last.GetAttribute("parentID") != parentId) @@ -544,8 +546,11 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; var xmlDocFragment = xmlDoc.CreateDocumentFragment(); xmlDocFragment.InnerXml = xml; - + last = (XmlElement)parent.AppendChild(xmlDocFragment); + + // fix sortOrder - see notes in UpdateSortOrder + last.Attributes["sortOrder"].Value = sortOrder.ToInvariantString(); } LogHelper.Debug("Done republishing Xml Index"); From 1e468cda5d440f676b6563667219251c5a68dfa1 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 17 May 2016 13:26:47 +0200 Subject: [PATCH 44/78] Removes unused method, ensures that Cloning only occurs once per request (sort of hacky). Before if you have a few nodes that are published but have pending changes, then perform a sort, then the xml will be cloned for as many times as there were content changes. --- .../umbraco.presentation/content.cs | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/content.cs b/src/Umbraco.Web/umbraco.presentation/content.cs index dc303c809d..7a53f38ccf 100644 --- a/src/Umbraco.Web/umbraco.presentation/content.cs +++ b/src/Umbraco.Web/umbraco.presentation/content.cs @@ -120,6 +120,7 @@ namespace umbraco private static readonly object DbReadSyncLock = new object(); private const string XmlContextContentItemKey = "UmbracoXmlContextContent"; + private const string XmlContextClonedContentItemKey = "UmbracoXmlContextContent.cloned"; private static string _umbracoXmlDiskCacheFileName = string.Empty; private volatile XmlDocument _xmlContent; @@ -685,11 +686,6 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; _persisterTask = _persisterTask.Touch(); // _persisterTask != null because SyncToXmlFile == true } - private static XmlDocument Clone(XmlDocument xmlDoc) - { - return xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); - } - private static XmlDocument EnsureSchema(string contentTypeAlias, XmlDocument xml) { string subset = null; @@ -750,13 +746,6 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; return SafeXmlReaderWriter.GetReader(this, releaser); } - // gets a locked safe read accses to the main xml - private async Task GetSafeXmlReaderAsync() - { - var releaser = await _xmlLock.LockAsync(); - return SafeXmlReaderWriter.GetReader(this, releaser); - } - // gets a locked safe write access to the main xml (cloned) private SafeXmlReaderWriter GetSafeXmlWriter(bool auto = true) { @@ -837,6 +826,28 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; _releaser.Dispose(); _releaser = null; } + + /// + /// This will clone the xml document - but we will try to only clone one time in a request + /// + /// + /// + private XmlDocument Clone(XmlDocument xmlDoc) + { + if (UmbracoContext.Current == null || UmbracoContext.Current.HttpContext == null) + { + //in this case we'll always clone + return xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); + } + + var clone = UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey]; + if (clone == null) + { + UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey] = xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); + } + + return (XmlDocument)UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey]; + } } private static string ChildNodesXPath From 512c19a13208ab7091c34174479fad10255b6f4a Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 17 May 2016 13:27:45 +0200 Subject: [PATCH 45/78] U4-8461 ERROR umbraco.presentation.webservices.nodeSorter - Could not update content sort order --- .../umbraco/webservices/nodeSorter.asmx.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs index 1ab2346054..e383e658aa 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/nodeSorter.asmx.cs @@ -192,7 +192,10 @@ namespace umbraco.presentation.webservices //content.Instance.SortNodes(parentId); //send notifications! TODO: This should be put somewhere centralized instead of hard coded directly here - ApplicationContext.Services.NotificationService.SendNotification(contentService.GetById(parentId), ActionSort.Instance, UmbracoContext, ApplicationContext); + if (parentId > 0) + { + ApplicationContext.Services.NotificationService.SendNotification(contentService.GetById(parentId), ActionSort.Instance, UmbracoContext, ApplicationContext); + } } catch (Exception ex) From 95871fde7c9c7ec71c7a89f774b3f316564b30bd Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 May 2016 15:22:49 +0200 Subject: [PATCH 46/78] updates naming conventions --- .../TestHelpers/BaseDatabaseFactoryTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index d24a411f73..996b7e2fff 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.TestHelpers private string _dbPath; //used to store (globally) the pre-built db with schema and initial data private static Byte[] _dbBytes; - private DefaultDatabaseFactory dbFactory; + private DefaultDatabaseFactory _dbFactory; [SetUp] public override void Initialize() @@ -67,7 +67,7 @@ namespace Umbraco.Tests.TestHelpers var path = TestHelper.CurrentAssemblyDirectory; AppDomain.CurrentDomain.SetData("DataDirectory", path); - dbFactory = new DefaultDatabaseFactory( + _dbFactory = new DefaultDatabaseFactory( GetDbConnectionString(), GetDbProviderName(), Logger); @@ -79,7 +79,7 @@ namespace Umbraco.Tests.TestHelpers { //TODO: Somehow make this faster - takes 5s + - DatabaseContext.Initialize(dbFactory.ProviderName, dbFactory.ConnectionString); + DatabaseContext.Initialize(_dbFactory.ProviderName, _dbFactory.ConnectionString); CreateSqlCeDatabase(); InitializeDatabase(); @@ -98,9 +98,9 @@ namespace Umbraco.Tests.TestHelpers var evtMsgs = new TransientMessagesFactory(); _appContext = new ApplicationContext( //assign the db context - new DatabaseContext(dbFactory, Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), + new DatabaseContext(_dbFactory, Logger, SqlSyntax, "System.Data.SqlServerCe.4.0"), //assign the service context - new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), cacheHelper, Logger, evtMsgs), + new ServiceContext(repositoryFactory, new PetaPocoUnitOfWorkProvider(_dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy(evtMsgs, Logger), cacheHelper, Logger, evtMsgs), cacheHelper, ProfilingLogger) { From 06ae15ee7c40a527d0c0d8f8b1c4dce990a55515 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 May 2016 16:12:12 +0200 Subject: [PATCH 47/78] reverts the cloning change --- .../umbraco.presentation/content.cs | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/content.cs b/src/Umbraco.Web/umbraco.presentation/content.cs index 7a53f38ccf..1e013da452 100644 --- a/src/Umbraco.Web/umbraco.presentation/content.cs +++ b/src/Umbraco.Web/umbraco.presentation/content.cs @@ -686,6 +686,11 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; _persisterTask = _persisterTask.Touch(); // _persisterTask != null because SyncToXmlFile == true } + private static XmlDocument Clone(XmlDocument xmlDoc) + { + return xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); + } + private static XmlDocument EnsureSchema(string contentTypeAlias, XmlDocument xml) { string subset = null; @@ -826,28 +831,7 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; _releaser.Dispose(); _releaser = null; } - - /// - /// This will clone the xml document - but we will try to only clone one time in a request - /// - /// - /// - private XmlDocument Clone(XmlDocument xmlDoc) - { - if (UmbracoContext.Current == null || UmbracoContext.Current.HttpContext == null) - { - //in this case we'll always clone - return xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); - } - - var clone = UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey]; - if (clone == null) - { - UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey] = xmlDoc == null ? null : (XmlDocument)xmlDoc.CloneNode(true); - } - - return (XmlDocument)UmbracoContext.Current.HttpContext.Items[XmlContextClonedContentItemKey]; - } + } private static string ChildNodesXPath From e54d374eb29b71edb84701fcdccd994302573296 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Fri, 20 May 2016 15:54:39 +0200 Subject: [PATCH 48/78] Add cmsPreviewXml table if it doesn't yet exist --- .../AddPreviewXmlTable.cs | 32 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + 2 files changed, 33 insertions(+) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourOneZero/AddPreviewXmlTable.cs diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourOneZero/AddPreviewXmlTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourOneZero/AddPreviewXmlTable.cs new file mode 100644 index 0000000000..4e8d3165fb --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionFourOneZero/AddPreviewXmlTable.cs @@ -0,0 +1,32 @@ +using System.Linq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourOneZero +{ + [Migration("4.1.0", 0, GlobalSettings.UmbracoMigrationName)] + public class AddPreviewXmlTable : MigrationBase + { + public AddPreviewXmlTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) + : base(sqlSyntax, logger) + { + } + + public override void Up() + { + var tableName = "cmsPreviewXml"; + var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); + if (tables.InvariantContains(tableName)) return; + + Create.Table(tableName) + .WithColumn("nodeId").AsInt32().NotNullable() + .WithColumn("versionId").AsGuid().NotNullable() + .WithColumn("timestamp").AsDateTime().NotNullable() + .WithColumn("xml").AsString(); + } + + public override void Down() + { } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2bbf4a7c7b..055be82ff1 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -415,6 +415,7 @@ + From 8c7390280e03f91936622636e2bb6db7d32b6e6c Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Fri, 20 May 2016 16:36:22 +0200 Subject: [PATCH 49/78] Updates this migration to only run when upgrading from 7.3.0 and higher --- .../TargetVersionSevenFiveZero/EnsureServersLockObject.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs index 6542bf4798..6f9d74e5db 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/EnsureServersLockObject.cs @@ -6,7 +6,10 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZero { - [Migration("7.5.0", 10, GlobalSettings.UmbracoMigrationName)] + // This migration exists for 7.3.0 but it seems like it was not always running properly + // if you're upgrading from 7.3.0 or higher than we add this migration, if you're upgrading + // from 7.3.0 or lower then you will already get this migration in the migration to get to 7.3.0 + [Migration("7.3.0", "7.5.0", 10, GlobalSettings.UmbracoMigrationName)] public class EnsureServersLockObject : MigrationBase { public EnsureServersLockObject(ISqlSyntaxProvider sqlSyntax, ILogger logger) From 2ffbdec14bc6b870b5d355d89e3a66f29b60d798 Mon Sep 17 00:00:00 2001 From: Gerard Konings Date: Fri, 20 May 2016 22:40:26 +0200 Subject: [PATCH 50/78] Removed required attribute from slider-handle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed required attribute. Slider defaults to round, so doesn’t need to be required --- .../src/views/propertyeditors/slider/handle.prevalues.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html index e12cb2a869..ae5deb099c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html @@ -1,5 +1,5 @@ 
    - From 3897d0f764b83a80e887f128367d9cd38994179d Mon Sep 17 00:00:00 2001 From: Gerard Konings Date: Fri, 20 May 2016 22:44:18 +0200 Subject: [PATCH 51/78] disable submitbutton disable submitbutton on overlay, so you can enable it later on --- .../src/views/components/overlays/umb-overlay.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html index 9bc0839122..472408468b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html @@ -66,6 +66,7 @@ label="{{model.submitButtonLabel}}" ng-if="model.submit && model.hideSubmitButton !== true" type="button" + disabled="model.disableSubmitButton" action="submitForm(model)">
    From d7cb79513f808e4b12ccd9f8d7aac6e24e5d6feb Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sat, 21 May 2016 21:49:00 +0200 Subject: [PATCH 52/78] Adjust login for narrow screen sizes. --- .../src/less/pages/login.less | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less index 6805783a86..51cb5aae38 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less @@ -13,7 +13,9 @@ left: 0; margin: 0 !important; padding: 0; + border: none; border-radius: 0; + overflow-y: auto; } @@ -50,7 +52,7 @@ } .login-overlay .form { - position:fixed; + position:relative; display: block; top: 100px; left: 165px; @@ -78,11 +80,25 @@ margin-top: 10px; } +@media (max-width: 767px) and (max-height: 420px){ + .login-overlay .form { + top: 60px; + } +} + @media (max-width: 565px) { // Remove padding on login-form on smaller devices .login-overlay .form { + top: 60px; + right: 25px; left: inherit; - right:25px; + padding-left: 25px; + padding-right:25px; + width: auto; + + input[type="text"], input[type="password"] { + width: 250px; + } } } From a8712fb4cf236d5664cd0908d628b9d2d9c6227e Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sat, 21 May 2016 21:51:28 +0200 Subject: [PATCH 53/78] Added a comment --- src/Umbraco.Web.UI.Client/src/less/pages/login.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less index 51cb5aae38..acd3df2556 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less @@ -81,6 +81,7 @@ } @media (max-width: 767px) and (max-height: 420px){ + // Move form closer to top on narrow screen sizes .login-overlay .form { top: 60px; } From ccd42ad1d42d554861afd88a97cc1cb66ae9c3f4 Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sat, 21 May 2016 22:42:58 +0200 Subject: [PATCH 54/78] Fix some issues in landscape mode --- src/Umbraco.Web.UI.Client/src/less/pages/login.less | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less index acd3df2556..892977180e 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less @@ -80,10 +80,10 @@ margin-top: 10px; } -@media (max-width: 767px) and (max-height: 420px){ +@media (max-width: 767px) and (max-height: 420px) and (orientation: landscape) { // Move form closer to top on narrow screen sizes .login-overlay .form { - top: 60px; + top: 50px; } } @@ -96,9 +96,13 @@ padding-left: 25px; padding-right:25px; width: auto; + } +} +@media (max-width: 339px) { + .login-overlay .form { input[type="text"], input[type="password"] { - width: 250px; + width: 250px; } } } From 3c9de3b20c371a4d1d44b90573388ec3961789ce Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sat, 21 May 2016 23:43:37 +0200 Subject: [PATCH 55/78] Ensure correct font is used for icon-check --- src/Umbraco.Web.UI.Client/src/less/tree.less | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index 86c9e4d081..dcbae04995 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -208,7 +208,9 @@ content: "\e165"; } -.umb-tree .umb-tree-node-checked i { +.umb-tree .umb-tree-node-checked i[class^="icon-"], +.umb-tree .umb-tree-node-checked i[class*=" icon-"] { + font-family: icomoon !important; color:@blue !important; } .umb-tree .umb-tree-node-checked i:before { From b74bf661b829d7d8eda3e0fe601baec0676eda5f Mon Sep 17 00:00:00 2001 From: bjarnef Date: Sat, 21 May 2016 23:57:30 +0200 Subject: [PATCH 56/78] Added quotes --- src/Umbraco.Web.UI.Client/src/less/tree.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index dcbae04995..d809418f2c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -210,7 +210,7 @@ .umb-tree .umb-tree-node-checked i[class^="icon-"], .umb-tree .umb-tree-node-checked i[class*=" icon-"] { - font-family: icomoon !important; + font-family: 'icomoon' !important; color:@blue !important; } .umb-tree .umb-tree-node-checked i:before { From 43d791f9a5549bf3a8b30800cee515386785d8c0 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 23 May 2016 08:27:30 +0200 Subject: [PATCH 57/78] U4-6504 SmtpClient Not Properly Disposed, Causing Emails to Fail Periodically --- .../umbraco.presentation/library.cs | 38 ++++---- .../businesslogic/translation/Translation.cs | 86 ++++++++++--------- 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index d9b1d520ed..5047aef271 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -1575,30 +1575,26 @@ namespace umbraco /// /// Sends an e-mail using the System.Net.Mail.MailMessage object /// - /// The sender of the e-mail - /// The recipient of the e-mail - /// E-mail subject - /// The complete content of the e-mail - /// Set to true when using Html formatted mails - public static void SendMail(string FromMail, string ToMail, string Subject, string Body, bool IsHtml) + /// The sender of the e-mail + /// The recipient(s) of the e-mail, add multiple email addresses by using a semicolon between them + /// E-mail subject + /// The complete content of the e-mail + /// Set to true when using Html formatted mails + public static void SendMail(string fromMail, string toMail, string subject, string body, bool isHtml) { try { - // create the mail message - MailMessage mail = new MailMessage(FromMail.Trim(), ToMail.Trim()); - - // populate the message - mail.Subject = Subject; - if (IsHtml) - mail.IsBodyHtml = true; - else - mail.IsBodyHtml = false; - - mail.Body = Body; - - // send it - SmtpClient smtpClient = new SmtpClient(); - smtpClient.Send(mail); + using (var mail = new MailMessage()) + { + mail.From = new MailAddress(fromMail.Trim()); + foreach (var mailAddress in toMail.Split(';')) + mail.To.Add(new MailAddress(mailAddress.Trim())); + mail.Subject = subject; + mail.IsBodyHtml = isHtml; + mail.Body = body; + using (var smtpClient = new SmtpClient()) + smtpClient.Send(mail); + } } catch (Exception ee) { diff --git a/src/umbraco.cms/businesslogic/translation/Translation.cs b/src/umbraco.cms/businesslogic/translation/Translation.cs index 7edbfefadd..deb4c32766 100644 --- a/src/umbraco.cms/businesslogic/translation/Translation.cs +++ b/src/umbraco.cms/businesslogic/translation/Translation.cs @@ -16,78 +16,80 @@ namespace umbraco.cms.businesslogic.translation [Obsolete("This will be removed in future versions, the translation utility will not work perfectly in v7.x")] public class Translation { - public static void MakeNew(CMSNode Node, User User, User Translator, Language Language, string Comment, - bool IncludeSubpages, bool SendEmail) + public static void MakeNew(CMSNode node, User user, User translator, Language language, string comment, bool includeSubpages, bool sendEmail) { // Get translation taskType for obsolete task constructor var taskType = ApplicationContext.Current.Services.TaskService.GetTaskTypeByAlias("toTranslate"); // Create pending task - Task t = new Task(new Umbraco.Core.Models.Task(taskType)); - t.Comment = Comment; - t.Node = Node; - t.ParentUser = User; - t.User = Translator; - t.Save(); + var task = new Task(new Umbraco.Core.Models.Task(taskType)) + { + Comment = comment, + Node = node, + ParentUser = user, + User = translator + }; + task.Save(); // Add log entry - Log.Add(LogTypes.SendToTranslate, User, Node.Id, - "Translator: " + Translator.Name + ", Language: " + Language.FriendlyName); + // Note: not updated to LogHelper as LogTypes.SendToTranslate might be something special, not sure + Log.Add(LogTypes.SendToTranslate, user, node.Id, "Translator: " + translator.Name + ", Language: " + language.FriendlyName); // send it - if (SendEmail) + if (sendEmail) { - string serverName = HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; - int port = HttpContext.Current.Request.Url.Port; + var serverName = HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; + var port = HttpContext.Current.Request.Url.Port; - if(port != 80) - serverName += ":" + port.ToString(); + if (port != 80) + serverName += ":" + port; serverName += IOHelper.ResolveUrl(SystemDirectories.Umbraco); // Send mail - string[] subjectVars = {serverName, Node.Text}; - string[] bodyVars = { - Translator.Name, Node.Text, User.Name, - serverName, t.Id.ToString(), - Language.FriendlyName + var subjectVars = new[] { serverName, node.Text }; + var bodyVars = new[] { + translator.Name, node.Text, user.Name, + serverName, task.Id.ToString(), + language.FriendlyName }; - if (User.Email != "" && User.Email.Contains("@") && Translator.Email != "" && - Translator.Email.Contains("@")) + if (string.IsNullOrWhiteSpace(user.Email) == false && user.Email.Contains("@") + && string.IsNullOrWhiteSpace(translator.Email) == false && translator.Email.Contains("@")) { - // create the mail message - MailMessage mail = new MailMessage(User.Email, Translator.Email); - - // populate the message - mail.Subject = ui.Text("translation", "mailSubject", subjectVars, Translator); - mail.IsBodyHtml = false; - mail.Body = ui.Text("translation", "mailBody", bodyVars, Translator); try { - SmtpClient sender = new SmtpClient(); - sender.Send(mail); + using (var mail = new MailMessage()) + { + mail.From = new MailAddress(user.Email.Trim()); + mail.To.Add(new MailAddress(translator.Email.Trim()); + mail.Subject = ui.Text("translation", "mailSubject", subjectVars, translator); ; + mail.IsBodyHtml = false; + mail.Body = ui.Text("translation", "mailBody", bodyVars, translator); ; + using (var smtpClient = new SmtpClient()) + smtpClient.Send(mail); + } } catch (Exception ex) { - LogHelper.Error("Error sending translation e-mail", ex); + LogHelper.Error("Error sending translation e-mail", ex); } } else { - LogHelper.Warn("Could not send translation e-mail because either user or translator lacks e-mail in settings"); + LogHelper.Warn("Could not send translation e-mail because either user or translator lacks e-mail in settings"); } - } - if (IncludeSubpages) + if (includeSubpages == false) + return; + + //store children array here because iterating over an Array property object is very inneficient. + var children = node.Children; + foreach (var child in children) { - //store children array here because iterating over an Array property object is very inneficient. - var c = Node.Children; - foreach (CMSNode n in c) - { - MakeNew(n, User, Translator, Language, Comment, true, false); - } + var cmsNode = (CMSNode) child; + MakeNew(cmsNode, user, translator, language, comment, true, false); } } @@ -123,7 +125,7 @@ namespace umbraco.cms.businesslogic.translation tmpStr = tmpStr.Replace("\r", " "); MatchCollection collection = Regex.Matches(tmpStr, @"[\S]+"); - return collection.Count; + return collection.Count; } } } \ No newline at end of file From 57b19e70173fd04716c8f562cb7205144f5e2ba6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 23 May 2016 08:47:36 +0200 Subject: [PATCH 58/78] Forgot semicolon, whoops! --- src/umbraco.cms/businesslogic/translation/Translation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/umbraco.cms/businesslogic/translation/Translation.cs b/src/umbraco.cms/businesslogic/translation/Translation.cs index deb4c32766..1cddf4e8e9 100644 --- a/src/umbraco.cms/businesslogic/translation/Translation.cs +++ b/src/umbraco.cms/businesslogic/translation/Translation.cs @@ -62,7 +62,7 @@ namespace umbraco.cms.businesslogic.translation using (var mail = new MailMessage()) { mail.From = new MailAddress(user.Email.Trim()); - mail.To.Add(new MailAddress(translator.Email.Trim()); + mail.To.Add(new MailAddress(translator.Email.Trim())); mail.Subject = ui.Text("translation", "mailSubject", subjectVars, translator); ; mail.IsBodyHtml = false; mail.Body = ui.Text("translation", "mailBody", bodyVars, translator); ; From bbe37ea6b9e6b17272eacf9900d14873d781e691 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 23 May 2016 08:55:51 +0200 Subject: [PATCH 59/78] U4-8349 Cannot create Scripting Files in Umbraco 7.4.0 --- .../umbraco/developer/Python/editPython.aspx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Python/editPython.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Python/editPython.aspx.cs index e6090fe676..563fb02055 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Python/editPython.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Python/editPython.aspx.cs @@ -46,7 +46,7 @@ namespace umbraco.cms.presentation.developer string file = Request.QueryString["file"]; string path = DeepLink.GetTreePathFromFilePath(file); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) .SyncTree(path, false); } } From c902649768c9f3f19f87751dd1fcc85bccc6eeca Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 23 May 2016 10:47:54 +0200 Subject: [PATCH 60/78] U4-8438 Umbraco 7.4.3 NuGet package missing file --- build/NuSpecs/tools/install.ps1 | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/build/NuSpecs/tools/install.ps1 b/build/NuSpecs/tools/install.ps1 index de7a6cc16e..5ebaa6d02a 100644 --- a/build/NuSpecs/tools/install.ps1 +++ b/build/NuSpecs/tools/install.ps1 @@ -77,8 +77,28 @@ if ($project) { { $packageWebConfigSource = Join-Path $installPath "UmbracoFiles\Web.config" Copy-Item $packageWebConfigSource $destinationWebConfig -Force - } + # Copy files that don't get automatically copied for Website projects + # We do this here, when copyWebconfig is true because we only want to do it for new installs + # If this is an upgrade then the files should already be there + $splashesSource = Join-Path $installPath "UmbracoFiles\Config\splashes\*.*" + $splashesDestination = Join-Path $projectPath "Config\splashes\" + New-Item $splashesDestination -Type directory + Copy-Item $splashesSource $splashesDestination -Force + + $sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*" + $sqlCe64Destination = Join-Path $projectPath "bin\amd64\" + Copy-Item $sqlCe64Source $sqlCe64Destination -Force + + $sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*" + $sqlCex86Destination = Join-Path $projectPath "bin\x86\" + Copy-Item $sqlCex86source $sqlCex86Destination -Force + + $umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml" + $umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml" + Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force + } + $installFolder = Join-Path $projectPath "Install" if(Test-Path $installFolder) { Remove-Item $installFolder -Force -Recurse -Confirm:$false From 9cf5ac2f95771eab8b5b261d4895577c311ef733 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 23 May 2016 17:44:45 +0200 Subject: [PATCH 61/78] U4-8491 Moving/Deleting Media does not sync/refresh the tree --- .../listview/listview.controller.js | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 518c27d110..3911ef7338 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -1,4 +1,4 @@ -function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService) { +function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) { //this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content // that isn't created yet, if we continue this will use the parent id in the route params which isn't what @@ -357,7 +357,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie $scope.actionInProgress = true; $scope.bulkStatus = getStatusMsg(0, selected.length); - serial(selected, fn, getStatusMsg, 0).then(function (result) { + return serial(selected, fn, getStatusMsg, 0).then(function (result) { // executes once the whole selection has been processed // in case of an error (caught by serial), result will be the error if (!(result.data && angular.isArray(result.data.notifications))) @@ -414,10 +414,36 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie function performMove(target) { - applySelected( - function (selected, index) { return contentResource.move({ parentId: target.id, id: getIdCallback(selected[index]) }); }, - function (count, total) { return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function (total) { return "Moved " + total + " item" + (total > 1 ? "s" : ""); }); + //NOTE: With the way this applySelected/serial works, I'm not sure there's a better way currently to return + // a specific value from one of the methods, so we'll have to try this way. Even though the first method + // will fire once per every node moved, the destination path will be the same and we need to use that to sync. + var newPath = null; + applySelected( + function(selected, index) { + return contentResource.move({ parentId: target.id, id: getIdCallback(selected[index]) }).then(function(path) { + newPath = path; + return path; + }); + }, + function(count, total) { + return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); + }, + function(total) { return "Moved " + total + " item" + (total > 1 ? "s" : ""); }) + .then(function() { + //executes if all is successful, let's sync the tree + if (newPath) { + + //we need to do a double sync here: first refresh the node where the content was moved, + // then refresh the node where the content was moved from + navigationService.syncTree({ tree: target.nodeType, path: newPath, forceReload: true, activate: false }).then(function (args) { + //get the currently edited node (if any) + var activeNode = appState.getTreeState("selectedNode"); + if (activeNode) { + navigationService.reloadNode(activeNode); + } + }); + } + }); } $scope.copy = function () { From 877b7d4af7147b0aef4a81eac7b602bf93b3d246 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 23 May 2016 19:23:59 +0200 Subject: [PATCH 62/78] U4-8358 Writers can't schedule publish/unpublish times --- src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index ede1dfc78d..efc9b7ced6 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -179,7 +179,7 @@ namespace Umbraco.Web.Models.Mapping Label = localizedText.Localize("content/releaseDate"), Value = display.ReleaseDate.HasValue ? display.ReleaseDate.Value.ToIsoString() : null, //Not editible for people without publish permission (U4-287) - View = display.AllowedActions.Contains('P') ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View + View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View //TODO: Fix up hard coded datepicker } , new ContentPropertyDisplay @@ -188,7 +188,7 @@ namespace Umbraco.Web.Models.Mapping Label = localizedText.Localize("content/unpublishDate"), Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null, //Not editible for people without publish permission (U4-287) - View = display.AllowedActions.Contains('P') ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View + View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View //TODO: Fix up hard coded datepicker }, new ContentPropertyDisplay From 3ea01b7dabbd6c51d8a7320313c674eb4f2befa9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 May 2016 15:04:46 +0200 Subject: [PATCH 63/78] U4-8445 Validation on the Email field for Members will not allow the entry of root domains greater than four characters. --- .../validation/nodirtycheck.directive.js | 0 .../umbsetdirtyonchange.directive.js | 0 .../validation/valCustom.directive.js | 0 .../validation/valHighlight.directive.js | 56 +-- .../validation/valcompare.directive.js | 46 +-- .../validation/valemail.directive.js | 9 +- .../validation/valformmanager.directive.js | 264 ++++++------ .../validation/valpropertymsg.directive.js | 390 +++++++++--------- .../valpropertyvalidator.directive.js | 0 .../validation/valregex.directive.js | 156 +++---- .../validation/valserver.directive.js | 186 ++++----- .../validation/valserverfield.directive.js | 130 +++--- .../validation/valtab.directive.js | 74 ++-- .../validation/valtogglemsg.directive.js | 178 ++++---- .../validation/valtriggerchange.directive.js | 0 15 files changed, 748 insertions(+), 741 deletions(-) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/nodirtycheck.directive.js (100%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/umbsetdirtyonchange.directive.js (100%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valCustom.directive.js (100%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valHighlight.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valcompare.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valemail.directive.js (72%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valformmanager.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valpropertymsg.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valpropertyvalidator.directive.js (100%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valregex.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valserver.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valserverfield.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valtab.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valtogglemsg.directive.js (97%) rename src/Umbraco.Web.UI.Client/src/common/directives/{components => }/validation/valtriggerchange.directive.js (100%) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/nodirtycheck.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js similarity index 100% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/nodirtycheck.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/nodirtycheck.directive.js diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/umbsetdirtyonchange.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js similarity index 100% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/umbsetdirtyonchange.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valCustom.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valCustom.directive.js similarity index 100% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valCustom.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valCustom.directive.js diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valHighlight.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valHighlight.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js index 2afd75eb29..9182441f8b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valHighlight.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valHighlight.directive.js @@ -1,28 +1,28 @@ -/** -* @ngdoc directive -* @name umbraco.directives.directive:valHighlight -* @restrict A -* @description Used on input fields when you want to signal that they are in error, this will highlight the item for 1 second -**/ -function valHighlight($timeout) { - return { - restrict: "A", - link: function (scope, element, attrs, ctrl) { - - attrs.$observe("valHighlight", function (newVal) { - if (newVal === "true") { - element.addClass("highlight-error"); - $timeout(function () { - //set the bound scope property to false - scope[attrs.valHighlight] = false; - }, 1000); - } - else { - element.removeClass("highlight-error"); - } - }); - - } - }; -} -angular.module('umbraco.directives.validation').directive("valHighlight", valHighlight); +/** +* @ngdoc directive +* @name umbraco.directives.directive:valHighlight +* @restrict A +* @description Used on input fields when you want to signal that they are in error, this will highlight the item for 1 second +**/ +function valHighlight($timeout) { + return { + restrict: "A", + link: function (scope, element, attrs, ctrl) { + + attrs.$observe("valHighlight", function (newVal) { + if (newVal === "true") { + element.addClass("highlight-error"); + $timeout(function () { + //set the bound scope property to false + scope[attrs.valHighlight] = false; + }, 1000); + } + else { + element.removeClass("highlight-error"); + } + }); + + } + }; +} +angular.module('umbraco.directives.validation').directive("valHighlight", valHighlight); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valcompare.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valcompare.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js index 31595273de..1a36dcc24f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valcompare.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js @@ -1,24 +1,24 @@ -angular.module('umbraco.directives.validation') - .directive('valCompare',function () { - return { - require: "ngModel", - link: function (scope, elem, attrs, ctrl) { - - //TODO: Pretty sure this should be done using a requires ^form in the directive declaration - var otherInput = elem.inheritedData("$formController")[attrs.valCompare]; - - ctrl.$parsers.push(function(value) { - if(value === otherInput.$viewValue) { - ctrl.$setValidity("valCompare", true); - return value; - } - ctrl.$setValidity("valCompare", false); - }); - - otherInput.$parsers.push(function(value) { - ctrl.$setValidity("valCompare", value === ctrl.$viewValue); - return value; - }); - } - }; +angular.module('umbraco.directives.validation') + .directive('valCompare',function () { + return { + require: "ngModel", + link: function (scope, elem, attrs, ctrl) { + + //TODO: Pretty sure this should be done using a requires ^form in the directive declaration + var otherInput = elem.inheritedData("$formController")[attrs.valCompare]; + + ctrl.$parsers.push(function(value) { + if(value === otherInput.$viewValue) { + ctrl.$setValidity("valCompare", true); + return value; + } + ctrl.$setValidity("valCompare", false); + }); + + otherInput.$parsers.push(function(value) { + ctrl.$setValidity("valCompare", value === ctrl.$viewValue); + return value; + }); + } + }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valemail.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js similarity index 72% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valemail.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js index 1e81d8edec..ade3403ad7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valemail.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js @@ -29,6 +29,12 @@ function valEmail(valEmailExpression) { } }; + //we need to remove the existing parsers = the default angular one which is created by + // type="email", but this has a regex issue, so we'll remove that and add our custom one + ctrl.$parsers.pop(); + //we also need to remove the existing formatter - the default angular one will not render + // what it thinks is an invalid email address, so it will just be blank + ctrl.$formatters.pop(); ctrl.$parsers.push(patternValidator); } }; @@ -36,7 +42,8 @@ function valEmail(valEmailExpression) { angular.module('umbraco.directives.validation') .directive("valEmail", valEmail) - .factory('valEmailExpression', function() { + .factory('valEmailExpression', function () { + //NOTE: This is the fixed regex which is part of the newer angular return { EMAIL_REGEXP: /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valformmanager.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 37c0313c45..9a00d5718c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -1,133 +1,133 @@ -/** -* @ngdoc directive -* @name umbraco.directives.directive:valFormManager -* @restrict A -* @require formController -* @description Used to broadcast an event to all elements inside this one to notify that form validation has -* changed. If we don't use this that means you have to put a watch for each directive on a form's validation -* changing which would result in much higher processing. We need to actually watch the whole $error collection of a form -* because just watching $valid or $invalid doesn't acurrately trigger form validation changing. -* This also sets the show-validation (or a custom) css class on the element when the form is invalid - this lets -* us css target elements to be displayed when the form is submitting/submitted. -* Another thing this directive does is to ensure that any .control-group that contains form elements that are invalid will -* be marked with the 'error' css class. This ensures that labels included in that control group are styled correctly. -**/ -function valFormManager(serverValidationManager, $rootScope, $log, $timeout, notificationsService, eventsService, $routeParams) { - return { - require: "form", - restrict: "A", - controller: function($scope) { - //This exposes an API for direct use with this directive - - var unsubscribe = []; - var self = this; - - //This is basically the same as a directive subscribing to an event but maybe a little - // nicer since the other directive can use this directive's API instead of a magical event - this.onValidationStatusChanged = function (cb) { - unsubscribe.push($scope.$on("valStatusChanged", function(evt, args) { - cb.apply(self, [evt, args]); - })); - }; - - //Ensure to remove the event handlers when this instance is destroyted - $scope.$on('$destroy', function () { - for (var u in unsubscribe) { - unsubscribe[u](); - } - }); - }, - link: function (scope, element, attr, formCtrl) { - - scope.$watch(function () { - return formCtrl.$error; - }, function (e) { - scope.$broadcast("valStatusChanged", { form: formCtrl }); - - //find all invalid elements' .control-group's and apply the error class - var inError = element.find(".control-group .ng-invalid").closest(".control-group"); - inError.addClass("error"); - - //find all control group's that have no error and ensure the class is removed - var noInError = element.find(".control-group .ng-valid").closest(".control-group").not(inError); - noInError.removeClass("error"); - - }, true); - - var className = attr.valShowValidation ? attr.valShowValidation : "show-validation"; - var savingEventName = attr.savingEvent ? attr.savingEvent : "formSubmitting"; - var savedEvent = attr.savedEvent ? attr.savingEvent : "formSubmitted"; - - //This tracks if the user is currently saving a new item, we use this to determine - // if we should display the warning dialog that they are leaving the page - if a new item - // is being saved we never want to display that dialog, this will also cause problems when there - // are server side validation issues. - var isSavingNewItem = false; - - //we should show validation if there are any msgs in the server validation collection - if (serverValidationManager.items.length > 0) { - element.addClass(className); - } - - var unsubscribe = []; - - //listen for the forms saving event - unsubscribe.push(scope.$on(savingEventName, function(ev, args) { - element.addClass(className); - - //set the flag so we can check to see if we should display the error. - isSavingNewItem = $routeParams.create; - })); - - //listen for the forms saved event - unsubscribe.push(scope.$on(savedEvent, function(ev, args) { - //remove validation class - element.removeClass(className); - - //clear form state as at this point we retrieve new data from the server - //and all validation will have cleared at this point - formCtrl.$setPristine(); - })); - - //This handles the 'unsaved changes' dialog which is triggered when a route is attempting to be changed but - // the form has pending changes - var locationEvent = $rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) { - if (!formCtrl.$dirty || isSavingNewItem) { - return; - } - - var path = nextLocation.split("#")[1]; - if (path) { - if (path.indexOf("%253") || path.indexOf("%252")) { - path = decodeURIComponent(path); - } - - if (!notificationsService.hasView()) { - var msg = { view: "confirmroutechange", args: { path: path, listener: locationEvent } }; - notificationsService.add(msg); - } - - //prevent the route! - event.preventDefault(); - - //raise an event - eventsService.emit("valFormManager.pendingChanges", true); - } - - }); - unsubscribe.push(locationEvent); - - //Ensure to remove the event handler when this instance is destroyted - scope.$on('$destroy', function() { - for (var u in unsubscribe) { - unsubscribe[u](); - } - }); - - $timeout(function(){ - formCtrl.$setPristine(); - }, 1000); - } - }; -} +/** +* @ngdoc directive +* @name umbraco.directives.directive:valFormManager +* @restrict A +* @require formController +* @description Used to broadcast an event to all elements inside this one to notify that form validation has +* changed. If we don't use this that means you have to put a watch for each directive on a form's validation +* changing which would result in much higher processing. We need to actually watch the whole $error collection of a form +* because just watching $valid or $invalid doesn't acurrately trigger form validation changing. +* This also sets the show-validation (or a custom) css class on the element when the form is invalid - this lets +* us css target elements to be displayed when the form is submitting/submitted. +* Another thing this directive does is to ensure that any .control-group that contains form elements that are invalid will +* be marked with the 'error' css class. This ensures that labels included in that control group are styled correctly. +**/ +function valFormManager(serverValidationManager, $rootScope, $log, $timeout, notificationsService, eventsService, $routeParams) { + return { + require: "form", + restrict: "A", + controller: function($scope) { + //This exposes an API for direct use with this directive + + var unsubscribe = []; + var self = this; + + //This is basically the same as a directive subscribing to an event but maybe a little + // nicer since the other directive can use this directive's API instead of a magical event + this.onValidationStatusChanged = function (cb) { + unsubscribe.push($scope.$on("valStatusChanged", function(evt, args) { + cb.apply(self, [evt, args]); + })); + }; + + //Ensure to remove the event handlers when this instance is destroyted + $scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + }, + link: function (scope, element, attr, formCtrl) { + + scope.$watch(function () { + return formCtrl.$error; + }, function (e) { + scope.$broadcast("valStatusChanged", { form: formCtrl }); + + //find all invalid elements' .control-group's and apply the error class + var inError = element.find(".control-group .ng-invalid").closest(".control-group"); + inError.addClass("error"); + + //find all control group's that have no error and ensure the class is removed + var noInError = element.find(".control-group .ng-valid").closest(".control-group").not(inError); + noInError.removeClass("error"); + + }, true); + + var className = attr.valShowValidation ? attr.valShowValidation : "show-validation"; + var savingEventName = attr.savingEvent ? attr.savingEvent : "formSubmitting"; + var savedEvent = attr.savedEvent ? attr.savingEvent : "formSubmitted"; + + //This tracks if the user is currently saving a new item, we use this to determine + // if we should display the warning dialog that they are leaving the page - if a new item + // is being saved we never want to display that dialog, this will also cause problems when there + // are server side validation issues. + var isSavingNewItem = false; + + //we should show validation if there are any msgs in the server validation collection + if (serverValidationManager.items.length > 0) { + element.addClass(className); + } + + var unsubscribe = []; + + //listen for the forms saving event + unsubscribe.push(scope.$on(savingEventName, function(ev, args) { + element.addClass(className); + + //set the flag so we can check to see if we should display the error. + isSavingNewItem = $routeParams.create; + })); + + //listen for the forms saved event + unsubscribe.push(scope.$on(savedEvent, function(ev, args) { + //remove validation class + element.removeClass(className); + + //clear form state as at this point we retrieve new data from the server + //and all validation will have cleared at this point + formCtrl.$setPristine(); + })); + + //This handles the 'unsaved changes' dialog which is triggered when a route is attempting to be changed but + // the form has pending changes + var locationEvent = $rootScope.$on('$locationChangeStart', function(event, nextLocation, currentLocation) { + if (!formCtrl.$dirty || isSavingNewItem) { + return; + } + + var path = nextLocation.split("#")[1]; + if (path) { + if (path.indexOf("%253") || path.indexOf("%252")) { + path = decodeURIComponent(path); + } + + if (!notificationsService.hasView()) { + var msg = { view: "confirmroutechange", args: { path: path, listener: locationEvent } }; + notificationsService.add(msg); + } + + //prevent the route! + event.preventDefault(); + + //raise an event + eventsService.emit("valFormManager.pendingChanges", true); + } + + }); + unsubscribe.push(locationEvent); + + //Ensure to remove the event handler when this instance is destroyted + scope.$on('$destroy', function() { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + + $timeout(function(){ + formCtrl.$setPristine(); + }, 1000); + } + }; +} angular.module('umbraco.directives.validation').directive("valFormManager", valFormManager); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valpropertymsg.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index eba308d830..be5da51702 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -1,196 +1,196 @@ -/** -* @ngdoc directive -* @name umbraco.directives.directive:valPropertyMsg -* @restrict A -* @element textarea -* @requires formController -* @description This directive is used to control the display of the property level validation message. -* We will listen for server side validation changes -* and when an error is detected for this property we'll show the error message. -* In order for this directive to work, the valStatusChanged directive must be placed on the containing form. -**/ -function valPropertyMsg(serverValidationManager) { - - return { - scope: { - property: "=" - }, - require: "^form", //require that this directive is contained within an ngForm - replace: true, //replace the element with the template - restrict: "E", //restrict to element - template: "
    {{errorMsg}}
    ", - - /** - Our directive requries a reference to a form controller - which gets passed in to this parameter - */ - link: function (scope, element, attrs, formCtrl) { - - var watcher = null; - - // Gets the error message to display - function getErrorMsg() { - //this can be null if no property was assigned - if (scope.property) { - //first try to get the error msg from the server collection - var err = serverValidationManager.getPropertyError(scope.property.alias, ""); - //if there's an error message use it - if (err && err.errorMsg) { - return err.errorMsg; - } - else { - return scope.property.propertyErrorMessage ? scope.property.propertyErrorMessage : "Property has errors"; - } - - } - return "Property has errors"; - } - - // We need to subscribe to any changes to our model (based on user input) - // This is required because when we have a server error we actually invalidate - // the form which means it cannot be resubmitted. - // So once a field is changed that has a server error assigned to it - // we need to re-validate it for the server side validator so the user can resubmit - // the form. Of course normal client-side validators will continue to execute. - function startWatch() { - //if there's not already a watch - if (!watcher) { - watcher = scope.$watch("property.value", function (newValue, oldValue) { - - if (!newValue || angular.equals(newValue, oldValue)) { - return; - } - - var errCount = 0; - for (var e in formCtrl.$error) { - if (angular.isArray(formCtrl.$error[e])) { - errCount++; - } - } - - //we are explicitly checking for valServer errors here, since we shouldn't auto clear - // based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg - // is the only one, then we'll clear. - - if ((errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { - scope.errorMsg = ""; - formCtrl.$setValidity('valPropertyMsg', true); - stopWatch(); - } - }, true); - } - } - - //clear the watch when the property validator is valid again - function stopWatch() { - if (watcher) { - watcher(); - watcher = null; - } - } - - //if there's any remaining errors in the server validation service then we should show them. - var showValidation = serverValidationManager.items.length > 0; - var hasError = false; - - //create properties on our custom scope so we can use it in our template - scope.errorMsg = ""; - - var unsubscribe = []; - - //listen for form error changes - unsubscribe.push(scope.$on("valStatusChanged", function(evt, args) { - if (args.form.$invalid) { - - //first we need to check if the valPropertyMsg validity is invalid - if (formCtrl.$error.valPropertyMsg && formCtrl.$error.valPropertyMsg.length > 0) { - //since we already have an error we'll just return since this means we've already set the - // hasError and errorMsg properties which occurs below in the serverValidationManager.subscribe - return; - } - else if (element.closest(".umb-control-group").find(".ng-invalid").length > 0) { - //check if it's one of the properties that is invalid in the current content property - hasError = true; - //update the validation message if we don't already have one assigned. - if (showValidation && scope.errorMsg === "") { - scope.errorMsg = getErrorMsg(); - } - } - else { - hasError = false; - scope.errorMsg = ""; - } - } - else { - hasError = false; - scope.errorMsg = ""; - } - }, true)); - - //listen for the forms saving event - unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { - showValidation = true; - if (hasError && scope.errorMsg === "") { - scope.errorMsg = getErrorMsg(); - } - else if (!hasError) { - scope.errorMsg = ""; - stopWatch(); - } - })); - - //listen for the forms saved event - unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { - showValidation = false; - scope.errorMsg = ""; - formCtrl.$setValidity('valPropertyMsg', true); - stopWatch(); - })); - - //listen for server validation changes - // NOTE: we pass in "" in order to listen for all validation changes to the content property, not for - // validation changes to fields in the property this is because some server side validators may not - // return the field name for which the error belongs too, just the property for which it belongs. - // It's important to note that we need to subscribe to server validation changes here because we always must - // indicate that a content property is invalid at the property level since developers may not actually implement - // the correct field validation in their property editors. - - if (scope.property) { //this can be null if no property was assigned - serverValidationManager.subscribe(scope.property.alias, "", function (isValid, propertyErrors, allErrors) { - hasError = !isValid; - if (hasError) { - //set the error message to the server message - scope.errorMsg = propertyErrors[0].errorMsg; - //flag that the current validator is invalid - formCtrl.$setValidity('valPropertyMsg', false); - startWatch(); - } - else { - scope.errorMsg = ""; - //flag that the current validator is valid - formCtrl.$setValidity('valPropertyMsg', true); - stopWatch(); - } - }); - - //when the element is disposed we need to unsubscribe! - // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain - // but they are a different callback instance than the above. - element.bind('$destroy', function () { - stopWatch(); - serverValidationManager.unsubscribe(scope.property.alias, ""); - }); - } - - //when the scope is disposed we need to unsubscribe - scope.$on('$destroy', function () { - for (var u in unsubscribe) { - unsubscribe[u](); - } - }); - } - - - }; -} +/** +* @ngdoc directive +* @name umbraco.directives.directive:valPropertyMsg +* @restrict A +* @element textarea +* @requires formController +* @description This directive is used to control the display of the property level validation message. +* We will listen for server side validation changes +* and when an error is detected for this property we'll show the error message. +* In order for this directive to work, the valStatusChanged directive must be placed on the containing form. +**/ +function valPropertyMsg(serverValidationManager) { + + return { + scope: { + property: "=" + }, + require: "^form", //require that this directive is contained within an ngForm + replace: true, //replace the element with the template + restrict: "E", //restrict to element + template: "
    {{errorMsg}}
    ", + + /** + Our directive requries a reference to a form controller + which gets passed in to this parameter + */ + link: function (scope, element, attrs, formCtrl) { + + var watcher = null; + + // Gets the error message to display + function getErrorMsg() { + //this can be null if no property was assigned + if (scope.property) { + //first try to get the error msg from the server collection + var err = serverValidationManager.getPropertyError(scope.property.alias, ""); + //if there's an error message use it + if (err && err.errorMsg) { + return err.errorMsg; + } + else { + return scope.property.propertyErrorMessage ? scope.property.propertyErrorMessage : "Property has errors"; + } + + } + return "Property has errors"; + } + + // We need to subscribe to any changes to our model (based on user input) + // This is required because when we have a server error we actually invalidate + // the form which means it cannot be resubmitted. + // So once a field is changed that has a server error assigned to it + // we need to re-validate it for the server side validator so the user can resubmit + // the form. Of course normal client-side validators will continue to execute. + function startWatch() { + //if there's not already a watch + if (!watcher) { + watcher = scope.$watch("property.value", function (newValue, oldValue) { + + if (!newValue || angular.equals(newValue, oldValue)) { + return; + } + + var errCount = 0; + for (var e in formCtrl.$error) { + if (angular.isArray(formCtrl.$error[e])) { + errCount++; + } + } + + //we are explicitly checking for valServer errors here, since we shouldn't auto clear + // based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg + // is the only one, then we'll clear. + + if ((errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { + scope.errorMsg = ""; + formCtrl.$setValidity('valPropertyMsg', true); + stopWatch(); + } + }, true); + } + } + + //clear the watch when the property validator is valid again + function stopWatch() { + if (watcher) { + watcher(); + watcher = null; + } + } + + //if there's any remaining errors in the server validation service then we should show them. + var showValidation = serverValidationManager.items.length > 0; + var hasError = false; + + //create properties on our custom scope so we can use it in our template + scope.errorMsg = ""; + + var unsubscribe = []; + + //listen for form error changes + unsubscribe.push(scope.$on("valStatusChanged", function(evt, args) { + if (args.form.$invalid) { + + //first we need to check if the valPropertyMsg validity is invalid + if (formCtrl.$error.valPropertyMsg && formCtrl.$error.valPropertyMsg.length > 0) { + //since we already have an error we'll just return since this means we've already set the + // hasError and errorMsg properties which occurs below in the serverValidationManager.subscribe + return; + } + else if (element.closest(".umb-control-group").find(".ng-invalid").length > 0) { + //check if it's one of the properties that is invalid in the current content property + hasError = true; + //update the validation message if we don't already have one assigned. + if (showValidation && scope.errorMsg === "") { + scope.errorMsg = getErrorMsg(); + } + } + else { + hasError = false; + scope.errorMsg = ""; + } + } + else { + hasError = false; + scope.errorMsg = ""; + } + }, true)); + + //listen for the forms saving event + unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { + showValidation = true; + if (hasError && scope.errorMsg === "") { + scope.errorMsg = getErrorMsg(); + } + else if (!hasError) { + scope.errorMsg = ""; + stopWatch(); + } + })); + + //listen for the forms saved event + unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { + showValidation = false; + scope.errorMsg = ""; + formCtrl.$setValidity('valPropertyMsg', true); + stopWatch(); + })); + + //listen for server validation changes + // NOTE: we pass in "" in order to listen for all validation changes to the content property, not for + // validation changes to fields in the property this is because some server side validators may not + // return the field name for which the error belongs too, just the property for which it belongs. + // It's important to note that we need to subscribe to server validation changes here because we always must + // indicate that a content property is invalid at the property level since developers may not actually implement + // the correct field validation in their property editors. + + if (scope.property) { //this can be null if no property was assigned + serverValidationManager.subscribe(scope.property.alias, "", function (isValid, propertyErrors, allErrors) { + hasError = !isValid; + if (hasError) { + //set the error message to the server message + scope.errorMsg = propertyErrors[0].errorMsg; + //flag that the current validator is invalid + formCtrl.$setValidity('valPropertyMsg', false); + startWatch(); + } + else { + scope.errorMsg = ""; + //flag that the current validator is valid + formCtrl.$setValidity('valPropertyMsg', true); + stopWatch(); + } + }); + + //when the element is disposed we need to unsubscribe! + // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain + // but they are a different callback instance than the above. + element.bind('$destroy', function () { + stopWatch(); + serverValidationManager.unsubscribe(scope.property.alias, ""); + }); + } + + //when the scope is disposed we need to unsubscribe + scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + } + + + }; +} angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valpropertyvalidator.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertyvalidator.directive.js similarity index 100% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valpropertyvalidator.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertyvalidator.directive.js diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valregex.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valregex.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js index 7bc3c6b877..6406583e77 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valregex.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js @@ -1,78 +1,78 @@ -/** - * @ngdoc directive - * @name umbraco.directives.directive:valRegex - * @restrict A - * @description A custom directive to allow for matching a value against a regex string. - * NOTE: there's already an ng-pattern but this requires that a regex expression is set, not a regex string - **/ -function valRegex() { - - return { - require: 'ngModel', - restrict: "A", - link: function (scope, elm, attrs, ctrl) { - - var flags = ""; - var regex; - var eventBindings = []; - - attrs.$observe("valRegexFlags", function (newVal) { - if (newVal) { - flags = newVal; - } - }); - - attrs.$observe("valRegex", function (newVal) { - if (newVal) { - try { - var resolved = newVal; - if (resolved) { - regex = new RegExp(resolved, flags); - } - else { - regex = new RegExp(attrs.valRegex, flags); - } - } - catch (e) { - regex = new RegExp(attrs.valRegex, flags); - } - } - }); - - eventBindings.push(scope.$watch('ngModel', function(newValue, oldValue){ - if(newValue && newValue !== oldValue) { - patternValidator(newValue); - } - })); - - var patternValidator = function (viewValue) { - if (regex) { - //NOTE: we don't validate on empty values, use required validator for that - if (!viewValue || regex.test(viewValue.toString())) { - // it is valid - ctrl.$setValidity('valRegex', true); - //assign a message to the validator - ctrl.errorMsg = ""; - return viewValue; - } - else { - // it is invalid, return undefined (no model update) - ctrl.$setValidity('valRegex', false); - //assign a message to the validator - ctrl.errorMsg = "Value is invalid, it does not match the correct pattern"; - return undefined; - } - } - }; - - scope.$on('$destroy', function(){ - // unbind watchers - for(var e in eventBindings) { - eventBindings[e](); - } - }); - - } - }; -} -angular.module('umbraco.directives.validation').directive("valRegex", valRegex); +/** + * @ngdoc directive + * @name umbraco.directives.directive:valRegex + * @restrict A + * @description A custom directive to allow for matching a value against a regex string. + * NOTE: there's already an ng-pattern but this requires that a regex expression is set, not a regex string + **/ +function valRegex() { + + return { + require: 'ngModel', + restrict: "A", + link: function (scope, elm, attrs, ctrl) { + + var flags = ""; + var regex; + var eventBindings = []; + + attrs.$observe("valRegexFlags", function (newVal) { + if (newVal) { + flags = newVal; + } + }); + + attrs.$observe("valRegex", function (newVal) { + if (newVal) { + try { + var resolved = newVal; + if (resolved) { + regex = new RegExp(resolved, flags); + } + else { + regex = new RegExp(attrs.valRegex, flags); + } + } + catch (e) { + regex = new RegExp(attrs.valRegex, flags); + } + } + }); + + eventBindings.push(scope.$watch('ngModel', function(newValue, oldValue){ + if(newValue && newValue !== oldValue) { + patternValidator(newValue); + } + })); + + var patternValidator = function (viewValue) { + if (regex) { + //NOTE: we don't validate on empty values, use required validator for that + if (!viewValue || regex.test(viewValue.toString())) { + // it is valid + ctrl.$setValidity('valRegex', true); + //assign a message to the validator + ctrl.errorMsg = ""; + return viewValue; + } + else { + // it is invalid, return undefined (no model update) + ctrl.$setValidity('valRegex', false); + //assign a message to the validator + ctrl.errorMsg = "Value is invalid, it does not match the correct pattern"; + return undefined; + } + } + }; + + scope.$on('$destroy', function(){ + // unbind watchers + for(var e in eventBindings) { + eventBindings[e](); + } + }); + + } + }; +} +angular.module('umbraco.directives.validation').directive("valRegex", valRegex); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserver.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js index 6225485073..1432a713c0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserver.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js @@ -1,94 +1,94 @@ -/** - * @ngdoc directive - * @name umbraco.directives.directive:valServer - * @restrict A - * @description This directive is used to associate a content property with a server-side validation response - * so that the validators in angular are updated based on server-side feedback. - **/ -function valServer(serverValidationManager) { - return { - require: ['ngModel', '?^umbProperty'], - restrict: "A", - link: function (scope, element, attr, ctrls) { - - var modelCtrl = ctrls[0]; - var umbPropCtrl = ctrls.length > 1 ? ctrls[1] : null; - if (!umbPropCtrl) { - //we cannot proceed, this validator will be disabled - return; - } - - var watcher = null; - - //Need to watch the value model for it to change, previously we had subscribed to - //modelCtrl.$viewChangeListeners but this is not good enough if you have an editor that - // doesn't specifically have a 2 way ng binding. This is required because when we - // have a server error we actually invalidate the form which means it cannot be - // resubmitted. So once a field is changed that has a server error assigned to it - // we need to re-validate it for the server side validator so the user can resubmit - // the form. Of course normal client-side validators will continue to execute. - function startWatch() { - //if there's not already a watch - if (!watcher) { - watcher = scope.$watch(function () { - return modelCtrl.$modelValue; - }, function (newValue, oldValue) { - - if (!newValue || angular.equals(newValue, oldValue)) { - return; - } - - if (modelCtrl.$invalid) { - modelCtrl.$setValidity('valServer', true); - stopWatch(); - } - }, true); - } - } - - function stopWatch() { - if (watcher) { - watcher(); - watcher = null; - } - } - - var currentProperty = umbPropCtrl.property; - - //default to 'value' if nothing is set - var fieldName = "value"; - if (attr.valServer) { - fieldName = scope.$eval(attr.valServer); - if (!fieldName) { - //eval returned nothing so just use the string - fieldName = attr.valServer; - } - } - - //subscribe to the server validation changes - serverValidationManager.subscribe(currentProperty.alias, fieldName, function (isValid, propertyErrors, allErrors) { - if (!isValid) { - modelCtrl.$setValidity('valServer', false); - //assign an error msg property to the current validator - modelCtrl.errorMsg = propertyErrors[0].errorMsg; - startWatch(); - } - else { - modelCtrl.$setValidity('valServer', true); - //reset the error message - modelCtrl.errorMsg = ""; - stopWatch(); - } - }); - - //when the element is disposed we need to unsubscribe! - // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain - // but they are a different callback instance than the above. - element.bind('$destroy', function () { - stopWatch(); - serverValidationManager.unsubscribe(currentProperty.alias, fieldName); - }); - } - }; -} +/** + * @ngdoc directive + * @name umbraco.directives.directive:valServer + * @restrict A + * @description This directive is used to associate a content property with a server-side validation response + * so that the validators in angular are updated based on server-side feedback. + **/ +function valServer(serverValidationManager) { + return { + require: ['ngModel', '?^umbProperty'], + restrict: "A", + link: function (scope, element, attr, ctrls) { + + var modelCtrl = ctrls[0]; + var umbPropCtrl = ctrls.length > 1 ? ctrls[1] : null; + if (!umbPropCtrl) { + //we cannot proceed, this validator will be disabled + return; + } + + var watcher = null; + + //Need to watch the value model for it to change, previously we had subscribed to + //modelCtrl.$viewChangeListeners but this is not good enough if you have an editor that + // doesn't specifically have a 2 way ng binding. This is required because when we + // have a server error we actually invalidate the form which means it cannot be + // resubmitted. So once a field is changed that has a server error assigned to it + // we need to re-validate it for the server side validator so the user can resubmit + // the form. Of course normal client-side validators will continue to execute. + function startWatch() { + //if there's not already a watch + if (!watcher) { + watcher = scope.$watch(function () { + return modelCtrl.$modelValue; + }, function (newValue, oldValue) { + + if (!newValue || angular.equals(newValue, oldValue)) { + return; + } + + if (modelCtrl.$invalid) { + modelCtrl.$setValidity('valServer', true); + stopWatch(); + } + }, true); + } + } + + function stopWatch() { + if (watcher) { + watcher(); + watcher = null; + } + } + + var currentProperty = umbPropCtrl.property; + + //default to 'value' if nothing is set + var fieldName = "value"; + if (attr.valServer) { + fieldName = scope.$eval(attr.valServer); + if (!fieldName) { + //eval returned nothing so just use the string + fieldName = attr.valServer; + } + } + + //subscribe to the server validation changes + serverValidationManager.subscribe(currentProperty.alias, fieldName, function (isValid, propertyErrors, allErrors) { + if (!isValid) { + modelCtrl.$setValidity('valServer', false); + //assign an error msg property to the current validator + modelCtrl.errorMsg = propertyErrors[0].errorMsg; + startWatch(); + } + else { + modelCtrl.$setValidity('valServer', true); + //reset the error message + modelCtrl.errorMsg = ""; + stopWatch(); + } + }); + + //when the element is disposed we need to unsubscribe! + // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain + // but they are a different callback instance than the above. + element.bind('$destroy', function () { + stopWatch(); + serverValidationManager.unsubscribe(currentProperty.alias, fieldName); + }); + } + }; +} angular.module('umbraco.directives.validation').directive("valServer", valServer); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserverfield.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserverfield.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js index 46fbaf93dd..1e0d2d8ba5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valserverfield.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js @@ -1,65 +1,65 @@ -/** - * @ngdoc directive - * @name umbraco.directives.directive:valServerField - * @restrict A - * @description This directive is used to associate a content field (not user defined) with a server-side validation response - * so that the validators in angular are updated based on server-side feedback. - **/ -function valServerField(serverValidationManager) { - return { - require: 'ngModel', - restrict: "A", - link: function (scope, element, attr, ctrl) { - - var fieldName = null; - var eventBindings = []; - - attr.$observe("valServerField", function (newVal) { - if (newVal && fieldName === null) { - fieldName = newVal; - - //subscribe to the changed event of the view model. This is required because when we - // have a server error we actually invalidate the form which means it cannot be - // resubmitted. So once a field is changed that has a server error assigned to it - // we need to re-validate it for the server side validator so the user can resubmit - // the form. Of course normal client-side validators will continue to execute. - eventBindings.push(scope.$watch('ngModel', function(newValue){ - if (ctrl.$invalid) { - ctrl.$setValidity('valServerField', true); - } - })); - - //subscribe to the server validation changes - serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) { - if (!isValid) { - ctrl.$setValidity('valServerField', false); - //assign an error msg property to the current validator - ctrl.errorMsg = fieldErrors[0].errorMsg; - } - else { - ctrl.$setValidity('valServerField', true); - //reset the error message - ctrl.errorMsg = ""; - } - }); - - //when the element is disposed we need to unsubscribe! - // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain - // but they are a different callback instance than the above. - element.bind('$destroy', function () { - serverValidationManager.unsubscribe(null, fieldName); - }); - } - }); - - scope.$on('$destroy', function(){ - // unbind watchers - for(var e in eventBindings) { - eventBindings[e](); - } - }); - - } - }; -} -angular.module('umbraco.directives.validation').directive("valServerField", valServerField); +/** + * @ngdoc directive + * @name umbraco.directives.directive:valServerField + * @restrict A + * @description This directive is used to associate a content field (not user defined) with a server-side validation response + * so that the validators in angular are updated based on server-side feedback. + **/ +function valServerField(serverValidationManager) { + return { + require: 'ngModel', + restrict: "A", + link: function (scope, element, attr, ctrl) { + + var fieldName = null; + var eventBindings = []; + + attr.$observe("valServerField", function (newVal) { + if (newVal && fieldName === null) { + fieldName = newVal; + + //subscribe to the changed event of the view model. This is required because when we + // have a server error we actually invalidate the form which means it cannot be + // resubmitted. So once a field is changed that has a server error assigned to it + // we need to re-validate it for the server side validator so the user can resubmit + // the form. Of course normal client-side validators will continue to execute. + eventBindings.push(scope.$watch('ngModel', function(newValue){ + if (ctrl.$invalid) { + ctrl.$setValidity('valServerField', true); + } + })); + + //subscribe to the server validation changes + serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) { + if (!isValid) { + ctrl.$setValidity('valServerField', false); + //assign an error msg property to the current validator + ctrl.errorMsg = fieldErrors[0].errorMsg; + } + else { + ctrl.$setValidity('valServerField', true); + //reset the error message + ctrl.errorMsg = ""; + } + }); + + //when the element is disposed we need to unsubscribe! + // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain + // but they are a different callback instance than the above. + element.bind('$destroy', function () { + serverValidationManager.unsubscribe(null, fieldName); + }); + } + }); + + scope.$on('$destroy', function(){ + // unbind watchers + for(var e in eventBindings) { + eventBindings[e](); + } + }); + + } + }; +} +angular.module('umbraco.directives.validation').directive("valServerField", valServerField); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtab.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtab.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js index fbca0cd233..8d1fc60083 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtab.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js @@ -1,38 +1,38 @@ - -/** -* @ngdoc directive -* @name umbraco.directives.directive:valTab -* @restrict A -* @description Used to show validation warnings for a tab to indicate that the tab content has validations errors in its data. -* In order for this directive to work, the valFormManager directive must be placed on the containing form. -**/ -function valTab() { - return { - require: ['^form', '^valFormManager'], - restrict: "A", - link: function (scope, element, attr, ctrs) { - - var valFormManager = ctrs[1]; - var tabId = "tab" + scope.tab.id; - scope.tabHasError = false; - - //listen for form validation changes - valFormManager.onValidationStatusChanged(function (evt, args) { - if (!args.form.$valid) { - var tabContent = element.closest(".umb-panel").find("#" + tabId); - //check if the validation messages are contained inside of this tabs - if (tabContent.find(".ng-invalid").length > 0) { - scope.tabHasError = true; - } else { - scope.tabHasError = false; - } - } - else { - scope.tabHasError = false; - } - }); - - } - }; -} + +/** +* @ngdoc directive +* @name umbraco.directives.directive:valTab +* @restrict A +* @description Used to show validation warnings for a tab to indicate that the tab content has validations errors in its data. +* In order for this directive to work, the valFormManager directive must be placed on the containing form. +**/ +function valTab() { + return { + require: ['^form', '^valFormManager'], + restrict: "A", + link: function (scope, element, attr, ctrs) { + + var valFormManager = ctrs[1]; + var tabId = "tab" + scope.tab.id; + scope.tabHasError = false; + + //listen for form validation changes + valFormManager.onValidationStatusChanged(function (evt, args) { + if (!args.form.$valid) { + var tabContent = element.closest(".umb-panel").find("#" + tabId); + //check if the validation messages are contained inside of this tabs + if (tabContent.find(".ng-invalid").length > 0) { + scope.tabHasError = true; + } else { + scope.tabHasError = false; + } + } + else { + scope.tabHasError = false; + } + }); + + } + }; +} angular.module('umbraco.directives.validation').directive("valTab", valTab); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js similarity index 97% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtogglemsg.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js index 43792a708a..304f151274 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtogglemsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js @@ -1,90 +1,90 @@ -function valToggleMsg(serverValidationManager) { - return { - require: "^form", - restrict: "A", - - /** - Our directive requries a reference to a form controller which gets passed in to this parameter - */ - link: function (scope, element, attr, formCtrl) { - - if (!attr.valToggleMsg){ - throw "valToggleMsg requires that a reference to a validator is specified"; - } - if (!attr.valMsgFor){ - throw "valToggleMsg requires that the attribute valMsgFor exists on the element"; - } - if (!formCtrl[attr.valMsgFor]) { - throw "valToggleMsg cannot find field " + attr.valMsgFor + " on form " + formCtrl.$name; - } - - //if there's any remaining errors in the server validation service then we should show them. - var showValidation = serverValidationManager.items.length > 0; - var hasCustomMsg = element.contents().length > 0; - - //add a watch to the validator for the value (i.e. myForm.value.$error.required ) - scope.$watch(function () { - //sometimes if a dialog closes in the middle of digest we can get null references here - - return (formCtrl && formCtrl[attr.valMsgFor]) ? formCtrl[attr.valMsgFor].$error[attr.valToggleMsg] : null; - }, function () { - //sometimes if a dialog closes in the middle of digest we can get null references here - if ((formCtrl && formCtrl[attr.valMsgFor])) { - if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg] && showValidation) { - element.show(); - //display the error message if this element has no contents - if (!hasCustomMsg) { - element.html(formCtrl[attr.valMsgFor].errorMsg); - } - } - else { - element.hide(); - } - } - }); - - var unsubscribe = []; - - //listen for the saving event (the result is a callback method which is called to unsubscribe) - unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { - showValidation = true; - if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg]) { - element.show(); - //display the error message if this element has no contents - if (!hasCustomMsg) { - element.html(formCtrl[attr.valMsgFor].errorMsg); - } - } - else { - element.hide(); - } - })); - - //listen for the saved event (the result is a callback method which is called to unsubscribe) - unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { - showValidation = false; - element.hide(); - })); - - //when the element is disposed we need to unsubscribe! - // NOTE: this is very important otherwise if this directive is part of a modal, the listener still exists because the dom - // element might still be there even after the modal has been hidden. - element.bind('$destroy', function () { - for (var u in unsubscribe) { - unsubscribe[u](); - } - }); - - } - }; -} - -/** -* @ngdoc directive -* @name umbraco.directives.directive:valToggleMsg -* @restrict A -* @element input -* @requires formController -* @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ? -**/ +function valToggleMsg(serverValidationManager) { + return { + require: "^form", + restrict: "A", + + /** + Our directive requries a reference to a form controller which gets passed in to this parameter + */ + link: function (scope, element, attr, formCtrl) { + + if (!attr.valToggleMsg){ + throw "valToggleMsg requires that a reference to a validator is specified"; + } + if (!attr.valMsgFor){ + throw "valToggleMsg requires that the attribute valMsgFor exists on the element"; + } + if (!formCtrl[attr.valMsgFor]) { + throw "valToggleMsg cannot find field " + attr.valMsgFor + " on form " + formCtrl.$name; + } + + //if there's any remaining errors in the server validation service then we should show them. + var showValidation = serverValidationManager.items.length > 0; + var hasCustomMsg = element.contents().length > 0; + + //add a watch to the validator for the value (i.e. myForm.value.$error.required ) + scope.$watch(function () { + //sometimes if a dialog closes in the middle of digest we can get null references here + + return (formCtrl && formCtrl[attr.valMsgFor]) ? formCtrl[attr.valMsgFor].$error[attr.valToggleMsg] : null; + }, function () { + //sometimes if a dialog closes in the middle of digest we can get null references here + if ((formCtrl && formCtrl[attr.valMsgFor])) { + if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg] && showValidation) { + element.show(); + //display the error message if this element has no contents + if (!hasCustomMsg) { + element.html(formCtrl[attr.valMsgFor].errorMsg); + } + } + else { + element.hide(); + } + } + }); + + var unsubscribe = []; + + //listen for the saving event (the result is a callback method which is called to unsubscribe) + unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { + showValidation = true; + if (formCtrl[attr.valMsgFor].$error[attr.valToggleMsg]) { + element.show(); + //display the error message if this element has no contents + if (!hasCustomMsg) { + element.html(formCtrl[attr.valMsgFor].errorMsg); + } + } + else { + element.hide(); + } + })); + + //listen for the saved event (the result is a callback method which is called to unsubscribe) + unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { + showValidation = false; + element.hide(); + })); + + //when the element is disposed we need to unsubscribe! + // NOTE: this is very important otherwise if this directive is part of a modal, the listener still exists because the dom + // element might still be there even after the modal has been hidden. + element.bind('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + + } + }; +} + +/** +* @ngdoc directive +* @name umbraco.directives.directive:valToggleMsg +* @restrict A +* @element input +* @requires formController +* @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ? +**/ angular.module('umbraco.directives.validation').directive("valToggleMsg", valToggleMsg); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtriggerchange.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js similarity index 100% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/validation/valtriggerchange.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js From f29b5aade7b14fec2c028abb44a30c29a35bd2b7 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 May 2016 15:07:35 +0200 Subject: [PATCH 64/78] only removes the buggy formatters/parsers if the attribute is type="email" --- .../directives/validation/valemail.directive.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js index ade3403ad7..8574d01f5a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valemail.directive.js @@ -29,12 +29,16 @@ function valEmail(valEmailExpression) { } }; - //we need to remove the existing parsers = the default angular one which is created by - // type="email", but this has a regex issue, so we'll remove that and add our custom one - ctrl.$parsers.pop(); - //we also need to remove the existing formatter - the default angular one will not render - // what it thinks is an invalid email address, so it will just be blank - ctrl.$formatters.pop(); + //if there is an attribute: type="email" then we need to remove those formatters and parsers + if (attrs.type === "email") { + //we need to remove the existing parsers = the default angular one which is created by + // type="email", but this has a regex issue, so we'll remove that and add our custom one + ctrl.$parsers.pop(); + //we also need to remove the existing formatter - the default angular one will not render + // what it thinks is an invalid email address, so it will just be blank + ctrl.$formatters.pop(); + } + ctrl.$parsers.push(patternValidator); } }; From 42021a56b21338a61b7ed6f7a726b63689419ce8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 24 May 2016 09:47:24 +0200 Subject: [PATCH 65/78] U4-8290 - minor cleanup & refactoring --- src/Umbraco.Core/Constants-PropertyEditors.cs | 21 ++++++----- src/Umbraco.Core/Models/PropertyType.cs | 2 +- .../PropertyEditorAttribute.cs | 4 +-- .../PropertyEditorValueTypes.cs | 31 ++++++++++------ .../PropertyEditors/PropertyValueEditor.cs | 35 ++++++++++-------- .../RequiredManifestValueValidator.cs | 2 +- .../ValueConverters/JsonValueConverter.cs | 2 +- src/Umbraco.Core/Services/DataTypeService.cs | 35 ++---------------- .../PropertyEditorValueEditorTests.cs | 28 +++++++-------- .../ContentPickerPropertyEditor.cs | 2 +- .../PropertyEditors/DatePropertyEditor.cs | 2 +- .../PropertyEditors/DateTimePropertyEditor.cs | 2 +- .../PropertyEditors/DecimalPropertyEditor.cs | 2 +- .../PropertyEditors/DropDownPropertyEditor.cs | 2 +- .../DropDownWithKeysPropertyEditor.cs | 2 +- .../PropertyEditors/GridPropertyEditor.cs | 2 +- .../ImageCropperPropertyEditor.cs | 2 +- .../PropertyEditors/IntegerPropertyEditor.cs | 2 +- .../PropertyEditors/LabelPropertyEditor.cs | 36 +++++++++++++------ .../MacroContainerPropertyEditor.cs | 2 +- .../PropertyEditors/MarkdownPropertyEditor.cs | 2 +- .../MediaPickerPropertyEditor.cs | 2 +- .../MemberPickerPropertyEditor.cs | 2 +- .../MultipleTextStringPropertyEditor.cs | 2 +- .../RadioButtonsPropertyEditor.cs | 2 +- .../RelatedLinksPropertyEditor.cs | 2 +- .../PropertyEditors/RichTextPropertyEditor.cs | 2 +- .../PropertyEditors/TextAreaPropertyEditor.cs | 2 +- .../TrueFalsePropertyEditor.cs | 2 +- .../UserPickerPropertyEditor.cs | 2 +- 30 files changed, 119 insertions(+), 117 deletions(-) diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 358ca0e5d7..80f118b58e 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core { /// /// Used to prefix generic properties that are internal content properties - /// + ///
    public const string InternalGenericPropertiesPrefix = "_umb_"; /// @@ -74,7 +74,7 @@ namespace Umbraco.Core /// [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string DictionaryPicker = "17B70066-F764-407D-AB05-3717F1E1C513"; - + /// /// Guid for the Dropdown list datatype. /// @@ -352,7 +352,7 @@ namespace Umbraco.Core ///
    [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string UltimatePicker = "CDBF0B5D-5CB2-445F-BC12-FCAAEC07CF2C"; - + /// /// Guid for the UltraSimpleEditor datatype. /// @@ -369,7 +369,7 @@ namespace Umbraco.Core ///
    [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string UmbracoUserControlWrapper = "D15E1281-E456-4B24-AA86-1DDA3E4299D5"; - + /// /// Guid for the Upload field datatype. /// @@ -420,11 +420,14 @@ namespace Umbraco.Core /// public const string EmailAddressAlias = "Umbraco.EmailAddress"; - /// - /// Pre-value name used to indicate a field that can be used to override the database field to which data for the associated - /// property is saved - /// - public const string DataValueTypePreValueKey = "umbracoDataValueType"; + public static class PreValueKeys + { + /// + /// Pre-value name used to indicate a field that can be used to override the database field to which data for the associated + /// property is saved + /// + public const string DataValueType = "umbracoDataValueType"; + } } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 00e7fc8d13..846b907197 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -436,7 +436,7 @@ namespace Umbraco.Core.Models { var propertyEditor = PropertyEditorResolver.Current.GetByAlias(_propertyEditorAlias); return propertyEditor.PreValueEditor.Fields - .SingleOrDefault(x => x.Key == Constants.PropertyEditors.DataValueTypePreValueKey) != null; + .SingleOrDefault(x => x.Key == Constants.PropertyEditors.PreValueKeys.DataValueType) != null; } /// diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs index dadbe5173f..d120753185 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.PropertyEditors EditorView = editorView; //defaults - ValueType = PropertyEditorValueTypes.StringType; + ValueType = PropertyEditorValueTypes.String; Icon = Constants.Icons.PropertyEditor; Group = "common"; } @@ -33,7 +33,7 @@ namespace Umbraco.Core.PropertyEditors Name = name; //defaults - ValueType = PropertyEditorValueTypes.StringType; + ValueType = PropertyEditorValueTypes.String; Icon = Constants.Icons.PropertyEditor; Group = "common"; } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorValueTypes.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorValueTypes.cs index 073e4388ca..0ece42d82b 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorValueTypes.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorValueTypes.cs @@ -1,25 +1,34 @@ -namespace Umbraco.Core.PropertyEditors +using System; + +namespace Umbraco.Core.PropertyEditors { public static class PropertyEditorValueTypes { - public const string DateType = "DATE"; + // mapped to DataTypeDatabaseType in DataTypeService.OverrideDatabaseTypeIfProvidedInPreValues + // BUT what about those that are not mapped? + // + // also mapped to DataTypeDatabaseType in PropertyValueEditor + // and this time the "+" are mapped - public const string DateTimeType = "DATETIME"; + public const string Date = "DATE"; // +Date - public const string DecimalType = "DECIMAL"; + public const string DateTime = "DATETIME"; // Date - public const string IntegerType = "INT"; + public const string Decimal = "DECIMAL"; // Decimal - public const string IntegerTypeAlternative = "INTEGER"; + public const string Integer = "INT"; // Integer - public const string JsonType = "JSON"; + [Obsolete("Use Integer.", false)] + public const string IntegerAlternative = "INTEGER"; // +Integer - public const string TextType = "TEXT"; + public const string Json = "JSON"; // +NText - public const string TimeType = "TIME"; + public const string Text = "TEXT"; // NText - public const string StringType = "STRING"; + public const string Time = "TIME"; // +Date - public const string XmlType = "XML"; + public const string String = "STRING"; // NVarchar + + public const string Xml = "XML"; // +NText } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs index a7154d7d67..0b083025f7 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.PropertyEditors /// public PropertyValueEditor() { - ValueType = PropertyEditorValueTypes.StringType; + ValueType = PropertyEditorValueTypes.String; //set a default for validators Validators = new List(); } @@ -123,30 +123,35 @@ namespace Umbraco.Core.PropertyEditors } /// - /// Returns the true DataTypeDatabaseType from the string representation ValueType + /// Returns the true DataTypeDatabaseType from the string representation ValueType. /// /// public DataTypeDatabaseType GetDatabaseType() { - switch (ValueType.ToUpper(CultureInfo.InvariantCulture)) + return GetDatabaseType(ValueType); + } + + public static DataTypeDatabaseType GetDatabaseType(string valueType) + { + switch (valueType.ToUpperInvariant()) { - case PropertyEditorValueTypes.IntegerType: - case PropertyEditorValueTypes.IntegerTypeAlternative: + case PropertyEditorValueTypes.Integer: + case PropertyEditorValueTypes.IntegerAlternative: return DataTypeDatabaseType.Integer; - case PropertyEditorValueTypes.DecimalType: + case PropertyEditorValueTypes.Decimal: return DataTypeDatabaseType.Decimal; - case PropertyEditorValueTypes.StringType: + case PropertyEditorValueTypes.String: return DataTypeDatabaseType.Nvarchar; - case PropertyEditorValueTypes.TextType: - case PropertyEditorValueTypes.JsonType: - case PropertyEditorValueTypes.XmlType: + case PropertyEditorValueTypes.Text: + case PropertyEditorValueTypes.Json: + case PropertyEditorValueTypes.Xml: return DataTypeDatabaseType.Ntext; - case PropertyEditorValueTypes.DateTimeType: - case PropertyEditorValueTypes.DateType: - case PropertyEditorValueTypes.TimeType: + case PropertyEditorValueTypes.DateTime: + case PropertyEditorValueTypes.Date: + case PropertyEditorValueTypes.Time: return DataTypeDatabaseType.Date; default: - throw new FormatException("The ValueType does not match a known value type"); + throw new ArgumentException("Not a valid value type.", "valueType"); } } @@ -238,7 +243,7 @@ namespace Umbraco.Core.PropertyEditors public virtual object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { //if it's json but it's empty json, then return null - if (ValueType.InvariantEquals(PropertyEditorValueTypes.JsonType) && editorValue.Value != null && editorValue.Value.ToString().DetectIsEmptyJson()) + if (ValueType.InvariantEquals(PropertyEditorValueTypes.Json) && editorValue.Value != null && editorValue.Value.ToString().DetectIsEmptyJson()) { return null; } diff --git a/src/Umbraco.Core/PropertyEditors/RequiredManifestValueValidator.cs b/src/Umbraco.Core/PropertyEditors/RequiredManifestValueValidator.cs index 842184d9ae..b3e8ff1f6f 100644 --- a/src/Umbraco.Core/PropertyEditors/RequiredManifestValueValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/RequiredManifestValueValidator.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.PropertyEditors { var asString = value.ToString(); - if (editor.ValueEditor.ValueType.InvariantEquals(PropertyEditorValueTypes.JsonType)) + if (editor.ValueEditor.ValueType.InvariantEquals(PropertyEditorValueTypes.Json)) { if (asString.DetectIsEmptyJson()) { diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/JsonValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/JsonValueConverter.cs index 60c2d7f667..c5f0236a1a 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/JsonValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/JsonValueConverter.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters { var propertyEditor = PropertyEditorResolver.Current.GetByAlias(propertyType.PropertyEditorAlias); if (propertyEditor == null) return false; - return propertyEditor.ValueEditor.ValueType.InvariantEquals(PropertyEditorValueTypes.JsonType); + return propertyEditor.ValueEditor.ValueType.InvariantEquals(PropertyEditorValueTypes.Json); } public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview) diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 75234fa3ab..2cdcfc76d5 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -504,7 +504,9 @@ namespace Umbraco.Core.Services if (Saving.IsRaisedEventCancelled(new SaveEventArgs(dataTypeDefinition), this)) return; - OverrideDatabaseTypeIfProvidedInPreValues(dataTypeDefinition, values); + // if preValues contain the data type, override the data type definition accordingly + if (values != null && values.ContainsKey(Constants.PropertyEditors.PreValueKeys.DataValueType)) + dataTypeDefinition.DatabaseType = PropertyValueEditor.GetDatabaseType(values[Constants.PropertyEditors.PreValueKeys.DataValueType].Value); var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateDataTypeDefinitionRepository(uow)) @@ -525,37 +527,6 @@ namespace Umbraco.Core.Services Audit(AuditType.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id); } - /// - /// If the database data field is provided in the pre-values update the data type definition to that instead of the - /// default for the property editor - /// - /// - /// - private static void OverrideDatabaseTypeIfProvidedInPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values) - { - if (values != null && values.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey)) - { - switch (values[Constants.PropertyEditors.DataValueTypePreValueKey].Value) - { - case PropertyEditorValueTypes.StringType: - dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Nvarchar; - break; - case PropertyEditorValueTypes.IntegerType: - dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Integer; - break; - case PropertyEditorValueTypes.DecimalType: - dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Decimal; - break; - case PropertyEditorValueTypes.DateTimeType: - dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Date; - break; - case PropertyEditorValueTypes.TextType: - dataTypeDefinition.DatabaseType = DataTypeDatabaseType.Ntext; - break; - } - } - } - /// /// Deletes an /// diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index eaa37b1f60..8fa332b108 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.PropertyEditors var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.StringType + ValueType = PropertyEditorValueTypes.String }; var result = valueEditor.ConvertDbToEditor(prop, prop.PropertyType, new Mock().Object); @@ -73,7 +73,7 @@ namespace Umbraco.Tests.PropertyEditors { var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DecimalType + ValueType = PropertyEditorValueTypes.Decimal }; var result = valueEditor.TryConvertValueToCrlType("12.34"); @@ -86,7 +86,7 @@ namespace Umbraco.Tests.PropertyEditors { var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DecimalType + ValueType = PropertyEditorValueTypes.Decimal }; var result = valueEditor.TryConvertValueToCrlType("12,34"); @@ -99,7 +99,7 @@ namespace Umbraco.Tests.PropertyEditors { var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DecimalType + ValueType = PropertyEditorValueTypes.Decimal }; var result = valueEditor.TryConvertValueToCrlType(string.Empty); @@ -112,7 +112,7 @@ namespace Umbraco.Tests.PropertyEditors { var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DateType + ValueType = PropertyEditorValueTypes.Date }; var result = valueEditor.TryConvertValueToCrlType("2010-02-05"); @@ -120,12 +120,12 @@ namespace Umbraco.Tests.PropertyEditors Assert.AreEqual(new DateTime(2010, 2, 5), result.Result); } - [TestCase(PropertyEditorValueTypes.StringType, "hello", "hello")] - [TestCase(PropertyEditorValueTypes.TextType, "hello", "hello")] - [TestCase(PropertyEditorValueTypes.IntegerType, 123, "123")] - [TestCase(PropertyEditorValueTypes.IntegerTypeAlternative, 123, "123")] - [TestCase(PropertyEditorValueTypes.IntegerType, "", "")] //test empty string for int - [TestCase(PropertyEditorValueTypes.DateTimeType, "", "")] //test empty string for date + [TestCase(PropertyEditorValueTypes.String, "hello", "hello")] + [TestCase(PropertyEditorValueTypes.Text, "hello", "hello")] + [TestCase(PropertyEditorValueTypes.Integer, 123, "123")] + [TestCase(PropertyEditorValueTypes.IntegerAlternative, 123, "123")] + [TestCase(PropertyEditorValueTypes.Integer, "", "")] //test empty string for int + [TestCase(PropertyEditorValueTypes.DateTime, "", "")] //test empty string for date public void Value_Editor_Can_Serialize_Value(string valueType, object val, string expected) { var prop = new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Nvarchar), val); @@ -145,7 +145,7 @@ namespace Umbraco.Tests.PropertyEditors var value = 12.34M; var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DecimalType + ValueType = PropertyEditorValueTypes.Decimal }; var prop = new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Decimal), value); @@ -159,7 +159,7 @@ namespace Umbraco.Tests.PropertyEditors { var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DecimalType + ValueType = PropertyEditorValueTypes.Decimal }; var prop = new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Decimal), string.Empty); @@ -174,7 +174,7 @@ namespace Umbraco.Tests.PropertyEditors var now = DateTime.Now; var valueEditor = new PropertyValueEditor { - ValueType = PropertyEditorValueTypes.DateType + ValueType = PropertyEditorValueTypes.Date }; var prop = new Property(1, Guid.NewGuid(), new PropertyType("test", DataTypeDatabaseType.Date), now); diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index 22c35e9b8c..4d58060164 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -4,7 +4,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "Content Picker", PropertyEditorValueTypes.IntegerType, "contentpicker", IsParameterEditor = true, Group = "Pickers")] + [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers")] public class ContentPickerPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/DatePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DatePropertyEditor.cs index 9cb8d5fec8..a98c96e759 100644 --- a/src/Umbraco.Web/PropertyEditors/DatePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DatePropertyEditor.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.DateAlias, "Date", PropertyEditorValueTypes.DateType, "datepicker", Icon="icon-calendar")] + [PropertyEditor(Constants.PropertyEditors.DateAlias, "Date", PropertyEditorValueTypes.Date, "datepicker", Icon="icon-calendar")] public class DatePropertyEditor : PropertyEditor { public DatePropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/DateTimePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DateTimePropertyEditor.cs index 1c6d7ce9d4..6291afd195 100644 --- a/src/Umbraco.Web/PropertyEditors/DateTimePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DateTimePropertyEditor.cs @@ -5,7 +5,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.DateTimeAlias, "Date/Time", "datepicker", ValueType = PropertyEditorValueTypes.DateTimeType, Icon="icon-time")] + [PropertyEditor(Constants.PropertyEditors.DateTimeAlias, "Date/Time", "datepicker", ValueType = PropertyEditorValueTypes.DateTime, Icon="icon-time")] public class DateTimePropertyEditor : PropertyEditor { public DateTimePropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs index 6a1a7d73a8..63c1964668 100644 --- a/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.DecimalAlias, "Decimal", PropertyEditorValueTypes.DecimalType, "decimal", IsParameterEditor = true)] + [PropertyEditor(Constants.PropertyEditors.DecimalAlias, "Decimal", PropertyEditorValueTypes.Decimal, "decimal", IsParameterEditor = true)] public class DecimalPropertyEditor : PropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs index 4a6f5321b8..115b99dea4 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.PropertyEditors /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published /// in cache and not the int ID. /// - [PropertyEditor(Constants.PropertyEditors.DropDownListAlias, "Dropdown list", "dropdown", ValueType = PropertyEditorValueTypes.StringType, Group = "lists", Icon = "icon-indent")] + [PropertyEditor(Constants.PropertyEditors.DropDownListAlias, "Dropdown list", "dropdown", ValueType = PropertyEditorValueTypes.String, Group = "lists", Icon = "icon-indent")] public class DropDownPropertyEditor : DropDownWithKeysPropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs index 6c947f4bad..a33115003c 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownWithKeysPropertyEditor.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web.PropertyEditors /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published /// in cache and not the string value. /// - [PropertyEditor(Constants.PropertyEditors.DropdownlistPublishingKeysAlias, "Dropdown list, publishing keys", "dropdown", ValueType = PropertyEditorValueTypes.IntegerType, Group = "lists", Icon = "icon-indent")] + [PropertyEditor(Constants.PropertyEditors.DropdownlistPublishingKeysAlias, "Dropdown list, publishing keys", "dropdown", ValueType = PropertyEditorValueTypes.Integer, Group = "lists", Icon = "icon-indent")] public class DropDownWithKeysPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 96ae6a1247..6178a4f9a4 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -16,7 +16,7 @@ using UmbracoExamine; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Core.Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = PropertyEditorValueTypes.JsonType, Group="rich content", Icon="icon-layout")] + [PropertyEditor(Core.Constants.PropertyEditors.GridAlias, "Grid layout", "grid", HideLabel = true, IsParameterEditor = false, ValueType = PropertyEditorValueTypes.Json, Group="rich content", Icon="icon-layout")] public class GridPropertyEditor : PropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs index b4fa34a670..1072448628 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs @@ -15,7 +15,7 @@ using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.ImageCropperAlias, "Image Cropper", "imagecropper", ValueType = PropertyEditorValueTypes.JsonType, HideLabel = false, Group="media", Icon="icon-crop")] + [PropertyEditor(Constants.PropertyEditors.ImageCropperAlias, "Image Cropper", "imagecropper", ValueType = PropertyEditorValueTypes.Json, HideLabel = false, Group="media", Icon="icon-crop")] public class ImageCropperPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/IntegerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/IntegerPropertyEditor.cs index f569905810..026aaf115f 100644 --- a/src/Umbraco.Web/PropertyEditors/IntegerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/IntegerPropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.IntegerAlias, "Numeric", "integer", IsParameterEditor = true, ValueType = PropertyEditorValueTypes.IntegerTypeAlternative)] + [PropertyEditor(Constants.PropertyEditors.IntegerAlias, "Numeric", "integer", IsParameterEditor = true, ValueType = PropertyEditorValueTypes.IntegerAlternative)] public class IntegerPropertyEditor : PropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs index fab9d0bba3..c5482695a3 100644 --- a/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/LabelPropertyEditor.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.PropertyEditors { return new LabelPreValueEditor(); } - + /// /// Custom value editor to mark it as readonly /// @@ -52,10 +52,10 @@ namespace Umbraco.Web.PropertyEditors Key = LegacyPropertyEditorValuesKey }); - ValueType = PropertyEditorValueTypes.StringType; + ValueType = PropertyEditorValueTypes.String; } - [PreValueField(Constants.PropertyEditors.DataValueTypePreValueKey, "Value type", "valuetype")] + [PreValueField(Constants.PropertyEditors.PreValueKeys.DataValueType, "Value type", "valuetype")] public string ValueType { get; set; } /// @@ -70,23 +70,23 @@ namespace Umbraco.Web.PropertyEditors var existing = base.ConvertDbToEditor(defaultPreVals, persistedPreVals); // Check for a saved value type. If not found set to default string type. - var valueType = PropertyEditorValueTypes.StringType; - if (existing.ContainsKey(Constants.PropertyEditors.DataValueTypePreValueKey)) + var valueType = PropertyEditorValueTypes.String; + if (existing.ContainsKey(Constants.PropertyEditors.PreValueKeys.DataValueType)) { - valueType = (string)existing[Constants.PropertyEditors.DataValueTypePreValueKey]; + valueType = (string)existing[Constants.PropertyEditors.PreValueKeys.DataValueType]; } // Convert any other values from a legacy property editor to a list, easier to enumerate on the editor. // Make sure to exclude values defined on the label property editor itself. var asList = existing .Select(e => new KeyValuePair(e.Key, e.Value)) - .Where(e => e.Key != Constants.PropertyEditors.DataValueTypePreValueKey) + .Where(e => e.Key != Constants.PropertyEditors.PreValueKeys.DataValueType) .ToList(); - var result = new Dictionary { { Constants.PropertyEditors.DataValueTypePreValueKey, valueType } }; + var result = new Dictionary { { Constants.PropertyEditors.PreValueKeys.DataValueType, valueType } }; if (asList.Any()) { - result.Add("values", asList); + result.Add(LegacyPropertyEditorValuesKey, asList); } return result; @@ -100,6 +100,20 @@ namespace Umbraco.Web.PropertyEditors /// public override IDictionary ConvertEditorToDb(IDictionary editorValue, PreValueCollection currentValue) { + // notes (from the PR): + // + // "All stemmed from the fact that even though the label property editor could have pre-values (from a legacy type), + // they couldn't up to now be edited and saved through the UI. Now that a "true" pre-value has been added, it can, + // which led to some odd behaviour. + // + // Firstly there would be a pre-value record saved for legacy values even if there aren't any (the key would exist + // but with no value). In that case I remove that pre-value so it's not saved(likely does no harm, but it's not + // necessary - we only need this legacy values pre-value record if there are any). + // + // Secondly if there are legacy values, I found on each save the JSON structure containing them would get repeatedly + // nested (an outer JSON wrapper would be added each time). So what I'm doing is if there are legacy pre-values, + // I'm converting what comes in "wrapped" like (below) into the legacy property editor values." + if (editorValue.ContainsKey(LegacyPropertyEditorValuesKey)) { // If provided value contains an empty legacy property editor values, don't save it @@ -110,8 +124,8 @@ namespace Umbraco.Web.PropertyEditors else { // If provided value contains legacy property editor values, unwrap the value to save so it doesn't get repeatedly nested on saves. - // This is a bit funky - but basically needing to parse out the original value from a JSON structure that is passed in - // looking like: + // This is a bit funky - but basically needing to parse out the original value from a JSON structure that is passed in + // looking like: // Value = {[ // { // "Key": "values", diff --git a/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs index ffe42b8603..3ac5788dd2 100644 --- a/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs @@ -9,7 +9,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MacroContainerAlias, "Macro container", "macrocontainer", ValueType = PropertyEditorValueTypes.TextType, Group="rich content", Icon="icon-settings-alt")] + [PropertyEditor(Constants.PropertyEditors.MacroContainerAlias, "Macro container", "macrocontainer", ValueType = PropertyEditorValueTypes.Text, Group="rich content", Icon="icon-settings-alt")] public class MacroContainerPropertyEditor : PropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/MarkdownPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MarkdownPropertyEditor.cs index 1da9ac57c6..9fa8f2d588 100644 --- a/src/Umbraco.Web/PropertyEditors/MarkdownPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MarkdownPropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MarkdownEditorAlias, "Markdown editor", "markdowneditor", ValueType = PropertyEditorValueTypes.TextType, Icon="icon-code", Group="rich content")] + [PropertyEditor(Constants.PropertyEditors.MarkdownEditorAlias, "Markdown editor", "markdowneditor", ValueType = PropertyEditorValueTypes.Text, Icon="icon-code", Group="rich content")] public class MarkdownPropertyEditor : PropertyEditor { protected override PreValueEditor CreatePreValueEditor() diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index d9a86da778..7e966d31ad 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -9,7 +9,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "Legacy Media Picker", PropertyEditorValueTypes.IntegerType, "mediapicker", Group="media", Icon="icon-picture")] + [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "Legacy Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group="media", Icon="icon-picture")] public class MediaPickerPropertyEditor : PropertyEditor { public MediaPickerPropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs index b35e4f7675..7dadbfe24c 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "Member Picker", PropertyEditorValueTypes.IntegerType, "memberpicker", Group = "People", Icon = "icon-user")] + [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user")] public class MemberPickerPropertyEditor : PropertyEditor { } diff --git a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs index 81885c8c55..96288c9857 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleTextStringPropertyEditor.cs @@ -14,7 +14,7 @@ using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MultipleTextstringAlias, "Repeatable textstrings", "multipletextbox", ValueType = PropertyEditorValueTypes.TextType, Icon="icon-ordered-list", Group="lists")] + [PropertyEditor(Constants.PropertyEditors.MultipleTextstringAlias, "Repeatable textstrings", "multipletextbox", ValueType = PropertyEditorValueTypes.Text, Icon="icon-ordered-list", Group="lists")] public class MultipleTextStringPropertyEditor : PropertyEditor { protected override PropertyValueEditor CreateValueEditor() diff --git a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs index 7704a4c178..2bcd8fcbd8 100644 --- a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web.PropertyEditors /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published /// in cache and not the string value. /// - [PropertyEditor(Constants.PropertyEditors.RadioButtonListAlias, "Radio button list", "radiobuttons", ValueType = PropertyEditorValueTypes.IntegerType, Group="lists", Icon="icon-target")] + [PropertyEditor(Constants.PropertyEditors.RadioButtonListAlias, "Radio button list", "radiobuttons", ValueType = PropertyEditorValueTypes.Integer, Group="lists", Icon="icon-target")] public class RadioButtonsPropertyEditor : DropDownWithKeysPropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs index 61faa6827f..cf9d4100a4 100644 --- a/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RelatedLinksPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.RelatedLinksAlias, "Related links", "relatedlinks", ValueType = PropertyEditorValueTypes.JsonType, Icon="icon-thumbnail-list", Group="pickers")] + [PropertyEditor(Constants.PropertyEditors.RelatedLinksAlias, "Related links", "relatedlinks", ValueType = PropertyEditorValueTypes.Json, Icon="icon-thumbnail-list", Group="pickers")] public class RelatedLinksPropertyEditor : PropertyEditor { protected override PreValueEditor CreatePreValueEditor() diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs index e069d09783..de65a326f7 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.TinyMCEAlias, "Rich Text Editor", "rte", ValueType = PropertyEditorValueTypes.TextType, HideLabel = false, Group="Rich Content", Icon="icon-browser-window")] + [PropertyEditor(Constants.PropertyEditors.TinyMCEAlias, "Rich Text Editor", "rte", ValueType = PropertyEditorValueTypes.Text, HideLabel = false, Group="Rich Content", Icon="icon-browser-window")] public class RichTextPropertyEditor : PropertyEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs index 3f7c6559b8..3bec23f004 100644 --- a/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TextAreaPropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.TextboxMultipleAlias, "Textarea", "textarea", IsParameterEditor = true, ValueType = PropertyEditorValueTypes.TextType, Icon="icon-application-window-alt")] + [PropertyEditor(Constants.PropertyEditors.TextboxMultipleAlias, "Textarea", "textarea", IsParameterEditor = true, ValueType = PropertyEditorValueTypes.Text, Icon="icon-application-window-alt")] public class TextAreaPropertyEditor : PropertyEditor { } diff --git a/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs index 012167a99c..0dc181cbc3 100644 --- a/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.TrueFalseAlias, "True/False", PropertyEditorValueTypes.IntegerType, "boolean", IsParameterEditor = true, Group = "Common", Icon="icon-checkbox")] + [PropertyEditor(Constants.PropertyEditors.TrueFalseAlias, "True/False", PropertyEditorValueTypes.Integer, "boolean", IsParameterEditor = true, Group = "Common", Icon="icon-checkbox")] public class TrueFalsePropertyEditor : PropertyEditor { protected override PreValueEditor CreatePreValueEditor() diff --git a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs index 4c08b26770..e4a070cb29 100644 --- a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs @@ -6,7 +6,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.IntegerType, "entitypicker", Group="People", Icon="icon-user")] + [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.Integer, "entitypicker", Group="People", Icon="icon-user")] public class UserPickerPropertyEditor : PropertyEditor { private IDictionary _defaultPreValues; From 6cb817fc0147950383782dba34ec365e1d2fa804 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 24 May 2016 16:20:20 +0200 Subject: [PATCH 66/78] U4-7332 Default gravatar link broken --- .../src/controllers/main.controller.js | 74 ++++++++++--------- .../Editors/BackOfficeController.cs | 4 + src/Umbraco.Web/Editors/GravatarController.cs | 38 ++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 4 files changed, 81 insertions(+), 36 deletions(-) create mode 100644 src/Umbraco.Web/Editors/GravatarController.cs diff --git a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js index 42d50b1ce7..0d3b56991e 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js @@ -19,7 +19,7 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ { value: "assets/img/application/logo@3x.png" } ]; $scope.touchDevice = appState.getGlobalState("touchDevice"); - + $scope.removeNotification = function (index) { notificationsService.remove(index); @@ -28,12 +28,12 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ $scope.closeDialogs = function (event) { //only close dialogs if non-link and non-buttons are clicked var el = event.target.nodeName; - var els = ["INPUT","A","BUTTON"]; + var els = ["INPUT", "A", "BUTTON"]; - if(els.indexOf(el) >= 0){return;} + if (els.indexOf(el) >= 0) { return; } var parents = $(event.target).parents("a,button"); - if(parents.length > 0){ + if (parents.length > 0) { return; } @@ -49,31 +49,31 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ var evts = []; //when a user logs out or timesout - evts.push(eventsService.on("app.notAuthenticated", function() { + evts.push(eventsService.on("app.notAuthenticated", function () { $scope.authenticated = null; $scope.user = null; })); - + //when the app is read/user is logged in, setup the data evts.push(eventsService.on("app.ready", function (evt, data) { - + $scope.authenticated = data.authenticated; $scope.user = data.user; - updateChecker.check().then(function(update){ - if(update && update !== "null"){ - if(update.type !== "None"){ + updateChecker.check().then(function(update) { + if (update && update !== "null") { + if (update.type !== "None") { var notification = { - headline: "Update available", - message: "Click to download", - sticky: true, - type: "info", - url: update.url + headline: "Update available", + message: "Click to download", + sticky: true, + type: "info", + url: update.url }; notificationsService.add(notification); } } - }) + }); //if the user has changed we need to redirect to the root so they don't try to continue editing the //last item in the URL (NOTE: the user id can equal zero, so we cannot just do !data.lastUserId since that will resolve to true) @@ -91,38 +91,40 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ if ($scope.user.emailHash) { //let's attempt to load the avatar, it might not exist or we might not have - // internet access so we'll detect it first - $http.get("https://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=404") + // internet access, well get an empty string back + $http.get(umbRequestHelper.getApiUrl("gravatarApiBaseUrl", "GetCurrentUserGravatarUrl")) .then( - function successCallback(response) { - $("#avatar-img").fadeTo(1000, 0, function () { - $scope.$apply(function () { - //this can be null if they time out - if ($scope.user && $scope.user.emailHash) { - var avatarBaseUrl = "https://www.gravatar.com/avatar/", - hash = $scope.user.emailHash; + function successCallback(response) { + // if we can't download the gravatar for some reason, an null gets returned, we cannot do anything + if (response.data !== "null") { + $("#avatar-img").fadeTo(1000, 0, function () { + $scope.$apply(function () { + //this can be null if they time out + if ($scope.user && $scope.user.emailHash) { + var avatarBaseUrl = "https://www.gravatar.com/avatar/", + hash = $scope.user.emailHash; - $scope.avatar = [ - { value: avatarBaseUrl + hash + ".jpg?s=30&d=mm" }, - { value: avatarBaseUrl + hash + ".jpg?s=60&d=mm" }, - { value: avatarBaseUrl + hash + ".jpg?s=90&d=mm" } - ]; - } + $scope.avatar = [ + { value: avatarBaseUrl + hash + ".jpg?s=30&d=mm" }, + { value: avatarBaseUrl + hash + ".jpg?s=60&d=mm" }, + { value: avatarBaseUrl + hash + ".jpg?s=90&d=mm" } + ]; + } + }); + $("#avatar-img").fadeTo(1000, 1); }); - $("#avatar-img").fadeTo(1000, 1); - }); + } }, function errorCallback(response) { //cannot load it from the server so we cannot do anything }); } - })); - evts.push(eventsService.on("app.ysod", function(name, error) { + evts.push(eventsService.on("app.ysod", function (name, error) { $scope.ysodOverlay = { view: "ysod", error: error, - show: true + show: true }; })); diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index b5cea7a945..95e1f7803e 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -291,6 +291,10 @@ namespace Umbraco.Web.Editors "logApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetEntityLog(0)) }, + { + "gravatarApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( + controller => controller.GetCurrentUserGravatarUrl()) + }, { "memberApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetByKey(Guid.Empty)) diff --git a/src/Umbraco.Web/Editors/GravatarController.cs b/src/Umbraco.Web/Editors/GravatarController.cs new file mode 100644 index 0000000000..f1e184dce7 --- /dev/null +++ b/src/Umbraco.Web/Editors/GravatarController.cs @@ -0,0 +1,38 @@ +using System; +using System.Net; +using Umbraco.Core; +using Umbraco.Web.Mvc; + +namespace Umbraco.Web.Editors +{ + /// + /// API controller used for getting Gravatar urls + /// + [PluginController("UmbracoApi")] + public class GravatarController : UmbracoAuthorizedJsonController + { + public string GetCurrentUserGravatarUrl() + { + var userService = Services.UserService; + var user = userService.GetUserById(UmbracoContext.Security.CurrentUser.Id); + var gravatarHash = user.Email.ToMd5(); + var gravatarUrl = "https://www.gravatar.com/avatar/" + gravatarHash; + + // Test if we can reach this URL, will fail when there's network or firewall errors + var request = (HttpWebRequest)WebRequest.Create(gravatarUrl); + // Require response within 10 seconds + request.Timeout = 10000; + try + { + using ((HttpWebResponse)request.GetResponse()) { } + } + catch (Exception) + { + // There was an HTTP or other error, return an null instead + return null; + } + + return gravatarUrl; + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 48005b1209..de4b49bc77 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -318,6 +318,7 @@ + From 85a54c64920c3335fc5b1382ffae797a4574be5f Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 May 2016 11:20:35 +0200 Subject: [PATCH 67/78] fixes the delete part of U4-8491 --- .../listview/listview.controller.js | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 3911ef7338..594475a7d2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -366,11 +366,24 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie } $scope.delete = function () { - applySelected( - function (selected, index) { return deleteItemCallback(getIdCallback(selected[index])); }, - function (count, total) { return "Deleted " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); }, - function (total) { return "Deleted " + total + " item" + (total > 1 ? "s" : ""); }, - "Sure you want to delete?"); + + var attempt = + applySelected( + function(selected, index) { return deleteItemCallback(getIdCallback(selected[index])); }, + function(count, total) { + return "Deleted " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); + }, + function(total) { return "Deleted " + total + " item" + (total > 1 ? "s" : ""); }, + "Sure you want to delete?"); + if (attempt) { + attempt.then(function () { + //executes if all is successful, let's sync the tree + var activeNode = appState.getTreeState("selectedNode"); + if (activeNode) { + navigationService.reloadNode(activeNode); + } + }); + } }; $scope.publish = function () { @@ -412,6 +425,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie }; + function performMove(target) { //NOTE: With the way this applySelected/serial works, I'm not sure there's a better way currently to return @@ -425,9 +439,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie return path; }); }, - function(count, total) { - return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : ""); - }, + function(count, total) {return "Moved " + count + " out of " + total + " item" + (total > 1 ? "s" : "");}, function(total) { return "Moved " + total + " item" + (total > 1 ? "s" : ""); }) .then(function() { //executes if all is successful, let's sync the tree From 247a5f415df1d216255a241a1d589d967aa90648 Mon Sep 17 00:00:00 2001 From: Claus Date: Wed, 25 May 2016 12:12:52 +0200 Subject: [PATCH 68/78] added a check to create macroScripts folder if it doesn't exist when creating a scripting file. --- .../umbraco/create/DLRScriptingTasks.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs index 1d9503e661..fd13010167 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core; @@ -42,6 +43,11 @@ namespace umbraco } } + var abFileFolder = Path.GetDirectoryName(abFileName); + if (string.IsNullOrWhiteSpace(abFileFolder) == false) + if (Directory.Exists(abFileFolder) == false) + Directory.CreateDirectory(abFileFolder); + var scriptWriter = System.IO.File.CreateText(abFileName); scriptWriter.Write(scriptContent); scriptWriter.Flush(); From 81d1ac74d2c9a271fc369deb1cb0e61038fe11b0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 May 2016 13:56:42 +0200 Subject: [PATCH 69/78] U4-8513 Fix the RestartApplicationPool extension to null out the current identity --- src/Umbraco.Web/ApplicationContextExtensions.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/ApplicationContextExtensions.cs b/src/Umbraco.Web/ApplicationContextExtensions.cs index 1756da5f3c..b91e73df0d 100644 --- a/src/Umbraco.Web/ApplicationContextExtensions.cs +++ b/src/Umbraco.Web/ApplicationContextExtensions.cs @@ -1,4 +1,5 @@ -using System.Web; +using System.Threading; +using System.Web; using Umbraco.Core; namespace Umbraco.Web @@ -17,8 +18,13 @@ namespace Umbraco.Web // it can check if this flag exists... if it does it means the app pool isn't restarted yet. http.Application.Add("AppPoolRestarting", true); - // unload app domain - HttpRuntime.UnloadAppDomain(); + // unload app domain - we must null out all identities otherwise we get serialization errors + // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue + http.User = null; + if (HttpContext.Current != null) + HttpContext.Current.User = null; + Thread.CurrentPrincipal = null; + HttpRuntime.UnloadAppDomain(); } } } From 1e38089bb4db835caeeba99046afaadd5ce656cc Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 May 2016 13:58:56 +0200 Subject: [PATCH 70/78] U4-8514 Fix installation issue when there are stale cookies on localhost --- src/umbraco.cms/businesslogic/Packager/Installer.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs index 4be82ba7b7..0225dd94a8 100644 --- a/src/umbraco.cms/businesslogic/Packager/Installer.cs +++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs @@ -14,6 +14,7 @@ using umbraco.cms.businesslogic.web; using umbraco.cms.businesslogic.propertytype; using umbraco.BusinessLogic; using System.Diagnostics; +using System.Security; using umbraco.cms.businesslogic.macro; using umbraco.cms.businesslogic.template; using umbraco.interfaces; @@ -304,13 +305,20 @@ namespace umbraco.cms.businesslogic.packager // Get current user, with a fallback var currentUser = new User(0); + + //if there's a context, try to resolve the user - this will return null if there is a context but no + // user found when there are old/invalid cookies lying around most likely during installation. + // in that case we'll keep using the admin user if (string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID) == false) { if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) { - currentUser = User.GetCurrent(); + var userById = User.GetCurrent(); + if (userById != null) + currentUser = userById; } } + //Xml as XElement which is used with the new PackagingService var rootElement = Config.DocumentElement.GetXElement(); From 8cea391a3f00c822f8e2aa4f0223d537d7c7fc42 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 May 2016 14:36:00 +0200 Subject: [PATCH 71/78] U4-8514 Fix installation issue when there are stale cookies on localhost --- src/Umbraco.Web/Install/InstallHelper.cs | 2 +- .../Install/InstallSteps/NewInstallStep.cs | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 143067f6a1..d39b16f6ac 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -42,7 +42,7 @@ namespace Umbraco.Web.Install { return new List { - new NewInstallStep(_umbContext.Application), + new NewInstallStep(_umbContext.HttpContext, _umbContext.Application), new UpgradeStep(), new FilePermissionsStep(), new MajorVersion7UpgradeReport(_umbContext.Application), diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index baa94c304e..4d8e9c5a4b 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; +using System.Web; using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -22,10 +23,12 @@ namespace Umbraco.Web.Install.InstallSteps "User", 20, "")] internal class NewInstallStep : InstallSetupStep { + private readonly HttpContextBase _http; private readonly ApplicationContext _applicationContext; - public NewInstallStep(ApplicationContext applicationContext) + public NewInstallStep(HttpContextBase http, ApplicationContext applicationContext) { + _http = http; _applicationContext = applicationContext; } @@ -111,7 +114,7 @@ namespace Umbraco.Web.Install.InstallSteps //the continue install UI : "continueinstall"; } } - + public override bool RequiresExecution(UserModel model) { //now we have to check if this is really a new install, the db might be configured and might contain data @@ -136,6 +139,10 @@ namespace Umbraco.Web.Install.InstallSteps } else { + // In this one case when it's a brand new install and nothing has been configured, make sure the + // back office cookie is cleared so there's no old cookies lying around causing problems + _http.ExpireCookie(UmbracoConfig.For.UmbracoSettings().Security.AuthCookieName); + return true; } } From def8ee4962bd755bcc51d82780891f8c08b4ed44 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 May 2016 14:38:24 +0200 Subject: [PATCH 72/78] fixes ysod when indexing grid content when the value is not a string (sub json value) --- .../PropertyEditors/GridPropertyEditor.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 6178a4f9a4..85177540d2 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -60,15 +60,21 @@ namespace Umbraco.Web.PropertyEditors foreach (var areaVal in areaVals) { - var str = areaVal.Value(); - str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; - sb.Append(str); - sb.Append(" "); + //TODO: If it's not a string, then it's a json formatted value - + // we cannot really index this in a smart way since it could be 'anything' + if (areaVal.Type == JTokenType.String) + { + var str = areaVal.Value(); + str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; + sb.Append(str); + sb.Append(" "); - //add the row name as an individual field - e.Document.Add( - new Field( - string.Format("{0}.{1}", field.Name, rowName), str, Field.Store.YES, Field.Index.ANALYZED)); + //add the row name as an individual field + e.Document.Add( + new Field( + string.Format("{0}.{1}", field.Name, rowName), str, Field.Store.YES, Field.Index.ANALYZED)); + } + } } From b3b4cd4654434e3a7db164dc8603d729285c7788 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 25 May 2016 15:30:35 +0200 Subject: [PATCH 73/78] Fixes: U4-8480 Allow deleting empty tab when creating a doctype --- .../src/views/components/umb-groups-builder.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 567d00c871..3533255288 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -49,7 +49,7 @@
    -
    +
    Date: Mon, 30 May 2016 10:01:34 +0200 Subject: [PATCH 74/78] Fixes: U4-8455 IE11 - Image Cropper stretches the image when zooming --- src/Umbraco.Web.UI.Client/src/less/property-editors.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index 96deaef09a..85a1d9e36c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -298,7 +298,7 @@ ul.color-picker li a { } .umb-cropper img { - max-width: initial; + max-width: none; } .umb-cropper .overlay, .umb-cropper-gravity .overlay { From 720a46686b31d1b2a9e0a732ee8c371c7dcc5f95 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 30 May 2016 12:02:13 +0200 Subject: [PATCH 75/78] U4-8500 Get c# docs building (#1291) fetches docfx, builds the metadata and builds the docs with the correct filters builds the UI docs from the same powershell script --- .gitignore | 8 +- apidocs/docfx.filter.yml | 18 ++ apidocs/docfx.json | 75 +++++ apidocs/index.md | 7 + apidocs/toc.yml | 5 + .../partials/class.tmpl.partial | 257 ++++++++++++++++++ .../partials/footer.tmpl.partial | 13 + .../partials/head.tmpl.partial | 18 ++ .../partials/namespace.tmpl.partial | 18 ++ .../partials/navbar.tmpl.partial | 22 ++ .../partials/rest.tmpl.partial | 101 +++++++ apidocs/umbracotemplate/styles/main.css | 73 +++++ build/ApiDocs/TOC.css | 170 ------------ build/ApiDocs/csharp-api-docs.shfbproj | 172 ------------ build/BuildDocs.bat | 20 ++ build/BuildDocs.ps1 | 109 ++++++-- .../docs/src/api/index.ngdoc | 12 +- src/Umbraco.Web.UI.Client/docs/umb-docs.css | 78 ++++++ src/Umbraco.Web.UI.Client/gruntFile.js | 8 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 2 +- src/umbraco.sln | 7 +- 21 files changed, 819 insertions(+), 374 deletions(-) create mode 100644 apidocs/docfx.filter.yml create mode 100644 apidocs/docfx.json create mode 100644 apidocs/index.md create mode 100644 apidocs/toc.yml create mode 100644 apidocs/umbracotemplate/partials/class.tmpl.partial create mode 100644 apidocs/umbracotemplate/partials/footer.tmpl.partial create mode 100644 apidocs/umbracotemplate/partials/head.tmpl.partial create mode 100644 apidocs/umbracotemplate/partials/namespace.tmpl.partial create mode 100644 apidocs/umbracotemplate/partials/navbar.tmpl.partial create mode 100644 apidocs/umbracotemplate/partials/rest.tmpl.partial create mode 100644 apidocs/umbracotemplate/styles/main.css delete mode 100644 build/ApiDocs/TOC.css delete mode 100644 build/ApiDocs/csharp-api-docs.shfbproj create mode 100644 build/BuildDocs.bat create mode 100644 src/Umbraco.Web.UI.Client/docs/umb-docs.css diff --git a/.gitignore b/.gitignore index 576beabdf9..543a67d7ff 100644 --- a/.gitignore +++ b/.gitignore @@ -132,4 +132,10 @@ src/umbraco.sln.ide/* build/UmbracoCms.*/ src/.vs/ src/Umbraco.Web.UI/umbraco/js/install.loader.js -src/Umbraco.Tests/media \ No newline at end of file +src/Umbraco.Tests/media +tools/docfx/* +apidocs/_site/* +apidocs/api/* +build/docs.zip +build/ui-docs.zip +build/csharp-docs.zip diff --git a/apidocs/docfx.filter.yml b/apidocs/docfx.filter.yml new file mode 100644 index 0000000000..e96fbaafff --- /dev/null +++ b/apidocs/docfx.filter.yml @@ -0,0 +1,18 @@ +apiRules: + - include: + uidRegex: ^Umbraco\.Core + - exclude: + uidRegex: ^umbraco\.Web\.org + - include: + uidRegex: ^Umbraco\.Web + - exclude: + hasAttribute: + uid: System.ComponentModel.EditorBrowsableAttribute + ctorArguments: + - System.ComponentModel.EditorBrowsableState.Never + - exclude: + uidRegex: ^umbraco\. + - exclude: + uidRegex: ^CookComputing\. + - exclude: + uidRegex: ^.*$ \ No newline at end of file diff --git a/apidocs/docfx.json b/apidocs/docfx.json new file mode 100644 index 0000000000..520622a0e0 --- /dev/null +++ b/apidocs/docfx.json @@ -0,0 +1,75 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "Umbraco.Core/Umbraco.Core.csproj", + "Umbraco.Web/Umbraco.Web.csproj" + ], + "exclude": [ + "**/obj/**", + "**/bin/**", + "_site/**" + ], + "cwd": "../src" + } + ], + "dest": "../apidocs/api", + "filter": "../apidocs/docfx.filter.yml" + } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md" + ] + }, + { + "files": [ + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "overwrite": [ + { + "files": [ + "**.md" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "globalMetadata": { + "_appTitle": "Umbraco c# Api docs", + "_enableSearch": true, + "_disableContribution": false + }, + "dest": "_site", + "template": [ + "default", "umbracotemplate" + ] + } +} \ No newline at end of file diff --git a/apidocs/index.md b/apidocs/index.md new file mode 100644 index 0000000000..b90b816312 --- /dev/null +++ b/apidocs/index.md @@ -0,0 +1,7 @@ + +# Umbraco c# API reference + +## Quick Links: + +### [Umbraco.Core](api/Umbraco.Core.html) docs +### [Umbraco.Web](api/Umbraco.Web.html) docs diff --git a/apidocs/toc.yml b/apidocs/toc.yml new file mode 100644 index 0000000000..6817825066 --- /dev/null +++ b/apidocs/toc.yml @@ -0,0 +1,5 @@ + +- name: Umbraco.Core Documentation + href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Core.html +- name: Umbraco.Web Documentation + href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Web.html \ No newline at end of file diff --git a/apidocs/umbracotemplate/partials/class.tmpl.partial b/apidocs/umbracotemplate/partials/class.tmpl.partial new file mode 100644 index 0000000000..9153a863a4 --- /dev/null +++ b/apidocs/umbracotemplate/partials/class.tmpl.partial @@ -0,0 +1,257 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + +{{^_disableContribution}} +{{#sourceurl}}{{__global.viewSource}}{{/sourceurl}} +{{/_disableContribution}} +

    {{>partials/title}}

    +
    {{{summary}}}
    +
    {{{conceptual}}}
    +{{#inheritance.0}} +
    +
    {{__global.inheritance}}
    +{{#inheritance}} +
    {{{specName.0.value}}}
    +{{/inheritance}} +
    {{item.name.0.value}}
    +
    +{{/inheritance.0}} +
    {{__global.namespace}}:{{namespace}}
    +
    {{__global.assembly}}:{{assemblies.0}}.dll
    +
    {{__global.syntax}}
    +
    +
    {{syntax.content.0.value}}
    +
    +{{#syntax.parameters.0}} +
    {{__global.parameters}}
    + + + + + + + + + +{{/syntax.parameters.0}} +{{#syntax.parameters}} + + + + + +{{/syntax.parameters}} +{{#syntax.parameters.0}} + +
    {{__global.type}}{{__global.name}}{{__global.description}}
    {{{type.specName.0.value}}}{{{id}}}{{{description}}}
    +{{/syntax.parameters.0}} +{{#syntax.return}} +
    {{__global.returns}}
    + + + + + + + + + + + + + +
    {{__global.type}}{{__global.description}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/syntax.return}} +{{#syntax.typeParameters.0}} +
    {{__global.typeParameters}}
    + + + + + + + + +{{/syntax.typeParameters.0}} +{{#syntax.typeParameters}} + + + + +{{/syntax.typeParameters}} +{{#syntax.typeParameters.0}} + +
    {{__global.name}}{{__global.description}}
    {{{id}}}{{{description}}}
    +{{/syntax.typeParameters.0}} +{{#remarks}} +
    {{__global.remarks}}
    +
    {{{remarks}}}
    +{{/remarks}} +{{#example.0}} +
    {{__global.examples}}
    +{{/example.0}} +{{#example}} +{{{.}}} +{{/example}} +{{#children}} +

    {{>partials/classSubtitle}}

    +{{#children}} +{{^_disableContribution}} +{{#sourceurl}} + + {{__global.viewSource}} +{{/sourceurl}} +{{/_disableContribution}} +

    {{name.0.value}}

    +
    {{{summary}}}
    +
    {{{conceptual}}}
    +
    {{__global.declaration}}
    +{{#syntax}} +
    +
    {{syntax.content.0.value}}
    +
    +{{#parameters.0}} +
    {{__global.parameters}}
    + + + + + + + + + +{{/parameters.0}} +{{#parameters}} + + + + + +{{/parameters}} +{{#parameters.0}} + +
    {{__global.type}}{{__global.name}}{{__global.description}}
    {{{type.specName.0.value}}}{{{id}}}{{{description}}}
    +{{/parameters.0}} +{{#return}} +
    {{__global.returns}}
    + + + + + + + + + + + + + +
    {{__global.type}}{{__global.description}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/return}} +{{#typeParameters.0}} +
    {{__global.typeParameters}}
    + + + + + + + + +{{/typeParameters.0}} +{{#typeParameters}} + + + + +{{/typeParameters}} +{{#typeParameters.0}} + +
    {{__global.name}}{{__global.description}}
    {{{id}}}{{{description}}}
    +{{/typeParameters.0}} +{{#fieldValue}} +
    {{__global.fieldValue}}
    + + + + + + + + + + + + + +
    {{__global.type}}{{__global.description}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/fieldValue}} +{{#propertyValue}} +
    {{__global.propertyValue}}
    + + + + + + + + + + + + + +
    {{__global.type}}{{__global.description}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/propertyValue}} +{{#eventType}} +
    {{__global.eventType}}
    + + + + + + + + + + + + + +
    {{__global.type}}{{__global.description}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/eventType}} +{{/syntax}} +{{#remarks}} +
    {{__global.remarks}}
    +
    {{{remarks}}}
    +{{/remarks}} +{{#example.0}} +
    {{__global.examples}}
    +{{/example.0}} +{{#example}} +{{{.}}} +{{/example}} +{{#exceptions.0}} +
    {{__global.exceptions}}
    + + + + + + + + +{{/exceptions.0}} +{{#exceptions}} + + + + +{{/exceptions}} +{{#exceptions.0}} + +
    {{__global.type}}{{__global.condition}}
    {{{type.specName.0.value}}}{{{description}}}
    +{{/exceptions.0}} +{{/children}} +{{/children}} diff --git a/apidocs/umbracotemplate/partials/footer.tmpl.partial b/apidocs/umbracotemplate/partials/footer.tmpl.partial new file mode 100644 index 0000000000..69f51a101f --- /dev/null +++ b/apidocs/umbracotemplate/partials/footer.tmpl.partial @@ -0,0 +1,13 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + +
    +
    + +
    diff --git a/apidocs/umbracotemplate/partials/head.tmpl.partial b/apidocs/umbracotemplate/partials/head.tmpl.partial new file mode 100644 index 0000000000..591e1c1885 --- /dev/null +++ b/apidocs/umbracotemplate/partials/head.tmpl.partial @@ -0,0 +1,18 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + + + + + {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} + + + + {{#_description}}{{/_description}} + + + + + + + {{#_enableSearch}}{{/_enableSearch}} + diff --git a/apidocs/umbracotemplate/partials/namespace.tmpl.partial b/apidocs/umbracotemplate/partials/namespace.tmpl.partial new file mode 100644 index 0000000000..80ca30799a --- /dev/null +++ b/apidocs/umbracotemplate/partials/namespace.tmpl.partial @@ -0,0 +1,18 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + +{{^_disableContribution}} +{{#sourceurl}} +{{__global.viewSource}} +{{/sourceurl}} +{{/_disableContribution}} +

    {{>partials/title}}

    +
    {{{summary}}}
    +
    {{{conceptual}}}
    +
    {{{remarks}}}
    +{{#children}} +

    {{>partials/namespaceSubtitle}}

    + {{#children}} +

    {{{specName.0.value}}}

    +
    {{{summary}}}
    + {{/children}} +{{/children}} diff --git a/apidocs/umbracotemplate/partials/navbar.tmpl.partial b/apidocs/umbracotemplate/partials/navbar.tmpl.partial new file mode 100644 index 0000000000..e9ee0af1c7 --- /dev/null +++ b/apidocs/umbracotemplate/partials/navbar.tmpl.partial @@ -0,0 +1,22 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + + diff --git a/apidocs/umbracotemplate/partials/rest.tmpl.partial b/apidocs/umbracotemplate/partials/rest.tmpl.partial new file mode 100644 index 0000000000..4306bf7db1 --- /dev/null +++ b/apidocs/umbracotemplate/partials/rest.tmpl.partial @@ -0,0 +1,101 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + +{{^_disableContribution}} +{{#sourceurl}}View Source{{/sourceurl}} +{{/_disableContribution}} +

    {{name}}

    +{{#summary}} +
    {{{summary}}}
    +{{/summary}} +{{#description}} +
    {{{description}}}
    +{{/description}} +{{#conceptual}} +
    {{{conceptual}}}
    +{{/conceptual}} +{{#children}} +{{^_disableContribution}} +{{#sourceurl}} + + View Source +{{/sourceurl}} +{{/_disableContribution}} +

    {{operationId}}

    +{{#summary}} +
    {{{summary}}}
    +{{/summary}} +{{#description}} +
    {{{description}}}
    +{{/description}} +{{#conceptual}} +
    {{{conceptual}}}
    +{{/conceptual}} +
    Request
    +
    +
    {{operation}} {{path}}
    +
    +{{#parameters.0}} +
    Parameters
    + + + + + + + + + + +{{/parameters.0}} +{{#parameters}} + + + + + + + {{/parameters}} + {{#parameters.0}} + +
    NameTypeValueNotes
    {{#required}}*{{/required}}{{name}}{{type}}{{default}}{{{description}}}
    +{{/parameters.0}} +{{#responses.0}} +
    +
    Responses
    + + + + + + + + + +{{/responses.0}} +{{#responses}} + + + + + + {{/responses}} + {{#responses.0}} + +
    Status CodeDescriptionSamples
    {{statusCode}}{{{description}}} + {{#examples}} +
    + Mime type: {{mimeType}} +
    +
    {{content}}
    + {{/examples}} +
    +
    +{{/responses.0}} +{{#footer}} + +{{/footer}} +{{/children}} +{{#footer}} + +{{/footer}} + diff --git a/apidocs/umbracotemplate/styles/main.css b/apidocs/umbracotemplate/styles/main.css new file mode 100644 index 0000000000..7756b2f7d4 --- /dev/null +++ b/apidocs/umbracotemplate/styles/main.css @@ -0,0 +1,73 @@ +body { + color: rgba(0,0,0,.8); +} +.navbar-inverse { + background: #a3db78; +} +.navbar-inverse .navbar-nav>li>a, .navbar-inverse .navbar-text { + color: rgba(0,0,0,.8); +} + +.navbar-inverse { + border-color: transparent; +} + +.sidetoc { + background-color: #f5fbf1; +} +body .toc { + background-color: #f5fbf1; +} +.sidefilter { + background-color: #daf0c9; +} +.subnav { + background-color: #f5fbf1; +} + +.navbar-inverse .navbar-nav>.active>a { + color: rgba(0,0,0,.8); + background-color: #daf0c9; +} + +.navbar-inverse .navbar-nav>.active>a:focus, .navbar-inverse .navbar-nav>.active>a:hover { + color: rgba(0,0,0,.8); + background-color: #daf0c9; +} + +.btn-primary { + color: rgba(0,0,0,.8); + background-color: #fff; + border-color: rgba(0,0,0,.8); +} +.btn-primary:hover { + background-color: #daf0c9; + color: rgba(0,0,0,.8); + border-color: rgba(0,0,0,.8); +} + +.toc .nav > li > a { + color: rgba(0,0,0,.8); +} + +button, a { + color: #f36f21; +} + +button:hover, +button:focus, +a:hover, +a:focus { + color: #143653; + text-decoration: none; +} + +.navbar-header .navbar-brand { + background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat; + background-size: 40px auto; + width:50px; +} + +.toc .nav > li.active > a { + color: #f36f21; +} diff --git a/build/ApiDocs/TOC.css b/build/ApiDocs/TOC.css deleted file mode 100644 index 9c32aba214..0000000000 --- a/build/ApiDocs/TOC.css +++ /dev/null @@ -1,170 +0,0 @@ -/* File : TOC.css -// Author : Eric Woodruff (Eric@EWoodruff.us) -// Updated : 09/07/2007 -// -// Stylesheet for the table of content -*/ - -* -{ - margin: 0px 0px 0px 0px; - padding: 0px 0px 0px 0px; -} - -body -{ - font-family: Segoe UI, Arial, Verdana, Helvetica, sans-serif; - font-size: 0.9em; - background-color: white; - color: White; - overflow: hidden; -} - -input -{ - padding:5px; - margin: 3px 0px 3px 0px -} - -img -{ - border: 0; - margin-left: 5px; - margin-right: 2px; -} - -img.TreeNodeImg -{ - cursor: pointer; -} - -img.TOCLink -{ - cursor: pointer; - margin-left: 0; - margin-right: 0; -} - -a.SelectedNode, a.UnselectedNode -{ - color: #333; - text-decoration: none; - padding: 1px 3px 1px 3px; - white-space: nowrap; -} - -a.SelectedNode -{ - background-color: #ffffff; - border: solid 1px #999999; - padding: 0px 2px 0px 2px; -} - -a.UnselectedNode:hover, a.SelectedNode:hover -{ - background-color: #cccccc; - border: solid 1px #999999; - padding: 0px 2px 0px 2px; -} - -.Visible -{ - display: block; - margin-left: 2em; -} - -.Hidden -{ - display: none; -} - -.Tree -{ - background-color: #fff; - color: #333; - width: 300px; - overflow: auto; -} - -.TreeNode, .TreeItem -{ - white-space: nowrap; - margin: 2px 2px 2px 2px; -} - -.TOCDiv -{ - position: relative; - float: left; - width: 300px; - height: 100%; -} - -.TOCSizer -{ - clear: none; - float: left; - width: 10px; - height: 100%; - background-image: url("Splitter.gif"); - background-position:center center; - background-repeat:no-repeat; - position: relative; - cursor: w-resize; - border-left: solid 1px #CCC; -} - -.TopicContent -{ - position: relative; - float: right; - background-color: white; - height: 100%; -} - -.SearchOpts -{ - padding: 5px 5px 10px 5px; - color: black; - width: 300px; - border-bottom: solid lightgrey 1px; - height: 110px !important; -} - -.NavOpts -{ - padding: 5px 5px 6px 5px; - color: black; - width: 300px; - border-bottom: solid lightgrey 1px; -} - -.NavOpts img { - display:inline-block; - margin: 0px 5px 0px 5px; -} - -.IndexOpts -{ - padding: 5px 5px 6px 5px; - color: black; - width: 300px; - border-bottom: solid lightgrey 1px; -} - -.IndexItem -{ - white-space: nowrap; - margin: 2px 2px 2px 2px; -} - -.IndexSubItem -{ - white-space: nowrap; - margin: 2px 2px 2px 12px; -} - -.PaddedText -{ - margin: 10px 10px 10px 10px; -} diff --git a/build/ApiDocs/csharp-api-docs.shfbproj b/build/ApiDocs/csharp-api-docs.shfbproj deleted file mode 100644 index f635f2e2ee..0000000000 --- a/build/ApiDocs/csharp-api-docs.shfbproj +++ /dev/null @@ -1,172 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {cb4d85f1-7390-40ee-b41f-a724bb8fddea} - 1.9.5.0 - - Documentation - Documentation - Documentation - - .NET Framework 4.5 - .\Output\ - UmbracoClassLibrary - en-US - OnlyErrors - csharp-api-docs.log - Website - True - False - False - False - True - CSharp - Blank - False - VS2010 - False - Guid - Umbraco .Net Class Library - AboveNamespaces - Attributes, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - None - None - False - True - Summary, AutoDocumentCtors, AutoDocumentDispose - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/BuildDocs.bat b/build/BuildDocs.bat new file mode 100644 index 0000000000..9d0a04e1cd --- /dev/null +++ b/build/BuildDocs.bat @@ -0,0 +1,20 @@ +@ECHO OFF +SETLOCAL + +SET release=%1 +ECHO Installing Npm NuGet Package + +SET nuGetFolder=%CD%\..\src\packages\ +ECHO Configured packages folder: %nuGetFolder% +ECHO Current folder: %CD% + +%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet + +for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\" +for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\" + +ECHO Adding Npm and Node to path +REM SETLOCAL is on, so changes to the path not persist to the actual user's path +PATH=%npmPath%;%nodePath%;%PATH% + +Powershell.exe -ExecutionPolicy Unrestricted -File .\BuildDocs.ps1 \ No newline at end of file diff --git a/build/BuildDocs.ps1 b/build/BuildDocs.ps1 index 6f46a43fde..dcb3a85cc1 100644 --- a/build/BuildDocs.ps1 +++ b/build/BuildDocs.ps1 @@ -1,27 +1,100 @@ -##We cannot continue if sandcastle is not installed determined by env variable: SHFBROOT +$PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path); +$RepoRoot = (get-item $PSScriptFilePath).Directory.Parent.FullName; +$SolutionRoot = Join-Path -Path $RepoRoot "src"; +$ToolsRoot = Join-Path -Path $RepoRoot "tools"; +$DocFx = Join-Path -Path $ToolsRoot "docfx\docfx.exe" +$DocFxFolder = (Join-Path -Path $ToolsRoot "docfx") +$DocFxJson = Join-Path -Path $RepoRoot "apidocs\docfx.json" +$7Zip = Join-Path -Path $ToolsRoot "7zip\7za.exe" +$DocFxSiteOutput = Join-Path -Path $RepoRoot "apidocs\_site\*.*" +$NgDocsSiteOutput = Join-Path -Path $RepoRoot "src\Umbraco.Web.UI.Client\docs\api\*.*" +$ProgFiles86 = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)"); +$MSBuild = "$ProgFiles86\MSBuild\14.0\Bin\MSBuild.exe" -if (-not (Test-Path Env:\SHFBROOT)) -{ - throw "The docs cannot be build, install Sandcastle help file builder" + +################ Do the UI docs + +"Changing to Umbraco.Web.UI.Client folder" +cd .. +cd src\Umbraco.Web.UI.Client +Write-Host $(Get-Location) + +"Creating build folder so MSBuild doesn't run the whole grunt build" +if (-Not (Test-Path "build")) { + md "build" } -$PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path).FullName -$BuildRoot = Split-Path -Path $PSScriptFilePath -Parent -$OutputPath = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\Output" -$ProjFile = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\csharp-api-docs.shfbproj" +"Installing node" +# Check if Install-Product exists, should only exist on the build server +if (Get-Command Install-Product -errorAction SilentlyContinue) +{ + Install-Product node '' +} -"Building docs with project file: $ProjFile" +"Installing node modules" +& npm install -$MSBuild = "$Env:SYSTEMROOT\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" +"Installing grunt" +& npm install -g grunt-cli -# build it! -& $MSBuild "$ProjFile" +"Moving back to build folder" +cd .. +cd .. +cd build +Write-Host $(Get-Location) -# remove files left over -Remove-Item $BuildRoot\* -include csharp-api-docs.shfbproj_* + & grunt --gruntfile ../src/umbraco.web.ui.client/gruntfile.js docs -# copy our custom styles in -Copy-Item $BuildRoot\ApiDocs\TOC.css $OutputPath\TOC.css +# change baseUrl +$BaseUrl = "https://our.umbraco.org/apidocs/ui/" +$IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html" +(Get-Content $IndexPath).replace('location.href.replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath +# zip it -"" -"Done!" \ No newline at end of file +& $7Zip a -tzip ui-docs.zip $NgDocsSiteOutput -r + +################ Do the c# docs + +# Build the solution in debug mode +$SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln" +& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean +if (-not $?) +{ + throw "The MSBuild process returned an error code." +} +& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount +if (-not $?) +{ + throw "The MSBuild process returned an error code." +} + +# Go get docfx if we don't hae it +$FileExists = Test-Path $DocFx +If ($FileExists -eq $False) { + + If(!(Test-Path $DocFxFolder)) + { + New-Item $DocFxFolder -type directory + } + + $DocFxZip = Join-Path -Path $ToolsRoot "docfx\docfx.zip" + $DocFxSource = "https://github.com/dotnet/docfx/releases/download/v1.9.4/docfx.zip" + Invoke-WebRequest $DocFxSource -OutFile $DocFxZip + + #unzip it + & $7Zip e $DocFxZip "-o$DocFxFolder" +} + +#clear site +If(Test-Path(Join-Path -Path $RepoRoot "apidocs\_site")) +{ + Remove-Item $DocFxSiteOutput -recurse +} + +# run it! +& $DocFx metadata $DocFxJson +& $DocFx build $DocFxJson + +# zip it + +& $7Zip a -tzip csharp-docs.zip $DocFxSiteOutput -r diff --git a/src/Umbraco.Web.UI.Client/docs/src/api/index.ngdoc b/src/Umbraco.Web.UI.Client/docs/src/api/index.ngdoc index a7cf500744..74cc458b90 100644 --- a/src/Umbraco.Web.UI.Client/docs/src/api/index.ngdoc +++ b/src/Umbraco.Web.UI.Client/docs/src/api/index.ngdoc @@ -2,15 +2,9 @@ @name Umbraco 7 JS documentation @description -#Belle +#Umbraco Backoffice UI API documentation -Umbraco 7 UI, codename "Belle" Built on AngularJS, Lazyload.js and Twitter Bootstrap - -##Introduction -Slides from the initial demonstration of Belle done at the Umbraco DK Fest can be found here: - -http://rawgithub.com/umbraco/Belle/master/Presentation/index.html - +This documentation relates to the angular, js, css and less APIs for developing back office components ##Running the site with mocked data @@ -45,7 +39,7 @@ So run the command: sudo npm install grunt-cli -g -Now that you have node and grunt installed, you can open `/Umbraco.Belle.Client` in either `cmd.exe` or terminal and run: +Now that you have node and grunt installed, you can open `/Umbraco.Web.UI.Client` in either `cmd.exe` or terminal and run: grunt dev diff --git a/src/Umbraco.Web.UI.Client/docs/umb-docs.css b/src/Umbraco.Web.UI.Client/docs/umb-docs.css new file mode 100644 index 0000000000..eef0fcee39 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/docs/umb-docs.css @@ -0,0 +1,78 @@ + +html { + font-family: 'Segoe UI', Tahoma, Helvetica, sans-serif; +} +body { + font-family: 'Segoe UI', Tahoma, Helvetica, sans-serif; + +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1; + color: inherit; +} + +.content code { + font-family: inherit; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: rgba(0,0,0,.8); + text-shadow: none; +} + +.navbar-fixed-top .navbar-inner { + min-height: 50px; + background: #a3db78; +} + +.form-search .well { + background-color: #f5fbf1; +} + +.form-search > ul.nav > li.module { + background-color: #daf0c9; +} + +.breadcrumb { + background-color: #f5fbf1; +} + +a { + color: #f36f21; +} +a:hover { + text-decoration: none; + color: rgba(0,0,0,.8); +} +.nav-list > .active > a, .nav-list > .active > a:hover, .nav-list > .active > a:focus, +.form-search > .nav-list > .active > a, .form-search > .nav-list > .active > a:hover, .form-search > .nav-list > .active > a:focus { + color: #f36f21; + text-shadow: none; + background-color: inherit; +} + +.form-search > ul.nav > li > a { + color: rgba(0,0,0,.8); + text-shadow: none; +} + +.form-search > ul.nav > li > a:hover { + text-decoration: none; + background-color: inherit; + text-shadow: none; + color: #000; +} + +.header img { + width: 50px; + margin-top: 5px; +} diff --git a/src/Umbraco.Web.UI.Client/gruntFile.js b/src/Umbraco.Web.UI.Client/gruntFile.js index 0500e24c31..fcae3e6b62 100644 --- a/src/Umbraco.Web.UI.Client/gruntFile.js +++ b/src/Umbraco.Web.UI.Client/gruntFile.js @@ -380,8 +380,12 @@ module.exports = function (grunt) { options: { dest: 'docs/api', startPage: '/api', - title: "Umbraco 7", + title: "Umbraco Backoffice UI API Documentation", html5Mode: false, + styles: [ + 'docs/umb-docs.css' + ], + image: "https://our.umbraco.org/assets/images/logo.svg" }, api: { src: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'], @@ -390,7 +394,7 @@ module.exports = function (grunt) { tutorials: { src: [], title: '' - } + } }, eslint:{ diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 33d150490b..4bd0be1308 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -2426,7 +2426,7 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" - + diff --git a/src/umbraco.sln b/src/umbraco.sln index d97aebf4f2..f9267c0412 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Web.UI", "Umbraco.Web.UI\Umbraco.Web.UI.csproj", "{4C4C194C-B5E4-4991-8F87-4373E24CC19F}" EndProject @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2849E9D4 ..\build\Build.bat = ..\build\Build.bat ..\build\Build.proj = ..\build\Build.proj ..\build\BuildBelle.bat = ..\build\BuildBelle.bat + ..\build\BuildDocs.ps1 = ..\build\BuildDocs.ps1 ..\build\RevertToCleanInstall.bat = ..\build\RevertToCleanInstall.bat ..\build\RevertToEmptyInstall.bat = ..\build\RevertToEmptyInstall.bat SolutionInfo.cs = SolutionInfo.cs @@ -19,8 +20,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2849E9D4 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{FD962632-184C-4005-A5F3-E705D92FC645}" ProjectSection(SolutionItems) = preProject + ..\apidocs\docfx.filter.yml = ..\apidocs\docfx.filter.yml + ..\apidocs\docfx.json = ..\apidocs\docfx.json + ..\apidocs\index.md = ..\apidocs\index.md ..\LICENSE.md = ..\LICENSE.md ..\README.md = ..\README.md + ..\apidocs\toc.yml = ..\apidocs\toc.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B5BD12C1-A454-435E-8A46-FF4A364C0382}" From 9190855bcf6bca61a83df98c14a1e78c439665d0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 30 May 2016 14:08:30 +0200 Subject: [PATCH 76/78] add configuration to disable folder select --- .../propertyeditors/mediapicker/mediapicker.controller.js | 2 ++ .../PropertyEditors/MultipleMediaPickerPropertyEditor.cs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 9969af937d..bbf61a32d3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -6,6 +6,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl //check the pre-values for multi-picker var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false; var onlyImages = $scope.model.config.onlyImages && $scope.model.config.onlyImages !== '0' ? true : false; + var disableFolderSelect = $scope.model.config.disableFolderSelect && $scope.model.config.disableFolderSelect !== '0' ? true : false; if (!$scope.model.config.startNodeId) { userService.getCurrentUser().then(function (userData) { @@ -68,6 +69,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl startNodeId: $scope.model.config.startNodeId, multiPicker: multiPicker, onlyImages: onlyImages, + disableFolderSelect: disableFolderSelect, show: true, submit: function(model) { diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index bbb3ee6c17..37587d1c54 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -23,7 +23,10 @@ namespace Umbraco.Web.PropertyEditors public bool MultiPicker { get; set; } [PreValueField("onlyImages", "Pick only images", "boolean", Description = "Only let the editor choose images from media.")] - public bool OnlyImages { get; set; } + public bool OnlyImages { get; set; } + + [PreValueField("disableFolderSelect", "Disable folder select", "boolean", Description = "Do not allow folders to be picked.")] + public bool DisableFolderSelect { get; set; } [PreValueField("startNodeId", "Start node", "mediapicker")] public int StartNodeId { get; set; } From 4aa4a0301369d35b9c436ef82accf33a95520add Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 May 2016 14:25:47 +0200 Subject: [PATCH 77/78] U4-8511 Update moment.js to the version to 2.10.3 for release --- src/Umbraco.Web.UI.Client/bower.json | 3 +- src/Umbraco.Web.UI.Client/gruntFile.js | 4 + .../lib/moment/moment-with-locales.js | 9156 ----------------- 3 files changed, 6 insertions(+), 9157 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/moment/moment-with-locales.js diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index ab78d10380..d1397b5d4e 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -26,6 +26,7 @@ "ng-file-upload": "~7.3.8", "tinymce": "~4.1.10", "codemirror": "~5.3.0", - "angular-local-storage": "~0.2.3" + "angular-local-storage": "~0.2.3", + "moment": "~2.10.3" } } diff --git a/src/Umbraco.Web.UI.Client/gruntFile.js b/src/Umbraco.Web.UI.Client/gruntFile.js index fcae3e6b62..d5b785c54c 100644 --- a/src/Umbraco.Web.UI.Client/gruntFile.js +++ b/src/Umbraco.Web.UI.Client/gruntFile.js @@ -463,6 +463,10 @@ module.exports = function (grunt) { expand: true, ignorePackages: ['bootstrap'], packageSpecific: { + 'moment': { + keepExpandedHierarchy: false, + files: ['min/moment-with-locales.js'] + }, 'typeahead.js': { keepExpandedHierarchy: false, files: ['dist/typeahead.bundle.min.js'] diff --git a/src/Umbraco.Web.UI.Client/lib/moment/moment-with-locales.js b/src/Umbraco.Web.UI.Client/lib/moment/moment-with-locales.js deleted file mode 100644 index 23d06ef355..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/moment/moment-with-locales.js +++ /dev/null @@ -1,9156 +0,0 @@ -//! moment.js -//! version : 2.8.3 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com - -(function (undefined) { - /************************************ - Constants - ************************************/ - - var moment, - VERSION = '2.8.3', - // the global-scope this is NOT the global object in Node.js - globalScope = typeof global !== 'undefined' ? global : this, - oldGlobalMoment, - round = Math.round, - hasOwnProperty = Object.prototype.hasOwnProperty, - i, - - YEAR = 0, - MONTH = 1, - DATE = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECOND = 6, - - // internal storage for locale config files - locales = {}, - - // extra moment internal properties (plugins register props here) - momentProperties = [], - - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports), - - // ASP.NET json date format regex - aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, - aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, - - // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html - // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere - isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, - - // format tokens - formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, - - // parsing token regexes - parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 - parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 - parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 - parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 - parseTokenDigits = /\d+/, // nonzero number of digits - parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. - parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z - parseTokenT = /T/i, // T (ISO separator) - parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 - parseTokenOrdinal = /\d{1,2}/, - - //strict parsing regexes - parseTokenOneDigit = /\d/, // 0 - 9 - parseTokenTwoDigits = /\d\d/, // 00 - 99 - parseTokenThreeDigits = /\d{3}/, // 000 - 999 - parseTokenFourDigits = /\d{4}/, // 0000 - 9999 - parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 - parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf - - // iso 8601 regex - // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) - isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, - - isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - - isoDates = [ - ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], - ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], - ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], - ['GGGG-[W]WW', /\d{4}-W\d{2}/], - ['YYYY-DDD', /\d{4}-\d{3}/] - ], - - // iso time formats and regexes - isoTimes = [ - ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], - ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], - ['HH:mm', /(T| )\d\d:\d\d/], - ['HH', /(T| )\d\d/] - ], - - // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30'] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, - - // getter and setter names - proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), - unitMillisecondFactors = { - 'Milliseconds' : 1, - 'Seconds' : 1e3, - 'Minutes' : 6e4, - 'Hours' : 36e5, - 'Days' : 864e5, - 'Months' : 2592e6, - 'Years' : 31536e6 - }, - - unitAliases = { - ms : 'millisecond', - s : 'second', - m : 'minute', - h : 'hour', - d : 'day', - D : 'date', - w : 'week', - W : 'isoWeek', - M : 'month', - Q : 'quarter', - y : 'year', - DDD : 'dayOfYear', - e : 'weekday', - E : 'isoWeekday', - gg: 'weekYear', - GG: 'isoWeekYear' - }, - - camelFunctions = { - dayofyear : 'dayOfYear', - isoweekday : 'isoWeekday', - isoweek : 'isoWeek', - weekyear : 'weekYear', - isoweekyear : 'isoWeekYear' - }, - - // format function strings - formatFunctions = {}, - - // default relative time thresholds - relativeTimeThresholds = { - s: 45, // seconds to minute - m: 45, // minutes to hour - h: 22, // hours to day - d: 26, // days to month - M: 11 // months to year - }, - - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), - - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.localeData().monthsShort(this, format); - }, - MMMM : function (format) { - return this.localeData().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.localeData().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.localeData().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.localeData().weekdays(this, format); - }, - w : function () { - return this.week(); - }, - W : function () { - return this.isoWeek(); - }, - YY : function () { - return leftZeroFill(this.year() % 100, 2); - }, - YYYY : function () { - return leftZeroFill(this.year(), 4); - }, - YYYYY : function () { - return leftZeroFill(this.year(), 5); - }, - YYYYYY : function () { - var y = this.year(), sign = y >= 0 ? '+' : '-'; - return sign + leftZeroFill(Math.abs(y), 6); - }, - gg : function () { - return leftZeroFill(this.weekYear() % 100, 2); - }, - gggg : function () { - return leftZeroFill(this.weekYear(), 4); - }, - ggggg : function () { - return leftZeroFill(this.weekYear(), 5); - }, - GG : function () { - return leftZeroFill(this.isoWeekYear() % 100, 2); - }, - GGGG : function () { - return leftZeroFill(this.isoWeekYear(), 4); - }, - GGGGG : function () { - return leftZeroFill(this.isoWeekYear(), 5); - }, - e : function () { - return this.weekday(); - }, - E : function () { - return this.isoWeekday(); - }, - a : function () { - return this.localeData().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.localeData().meridiem(this.hours(), this.minutes(), false); - }, - H : function () { - return this.hours(); - }, - h : function () { - return this.hours() % 12 || 12; - }, - m : function () { - return this.minutes(); - }, - s : function () { - return this.seconds(); - }, - S : function () { - return toInt(this.milliseconds() / 100); - }, - SS : function () { - return leftZeroFill(toInt(this.milliseconds() / 10), 2); - }, - SSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - SSSS : function () { - return leftZeroFill(this.milliseconds(), 3); - }, - Z : function () { - var a = -this.zone(), - b = '+'; - if (a < 0) { - a = -a; - b = '-'; - } - return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); - }, - ZZ : function () { - var a = -this.zone(), - b = '+'; - if (a < 0) { - a = -a; - b = '-'; - } - return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); - }, - z : function () { - return this.zoneAbbr(); - }, - zz : function () { - return this.zoneName(); - }, - X : function () { - return this.unix(); - }, - Q : function () { - return this.quarter(); - } - }, - - deprecations = {}, - - lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; - - // Pick the first defined of two or three arguments. dfl comes from - // default. - function dfl(a, b, c) { - switch (arguments.length) { - case 2: return a != null ? a : b; - case 3: return a != null ? a : b != null ? b : c; - default: throw new Error('Implement me'); - } - } - - function hasOwnProp(a, b) { - return hasOwnProperty.call(a, b); - } - - function defaultParsingFlags() { - // We need to deep clone this object, and es5 standard is not very - // helpful. - return { - empty : false, - unusedTokens : [], - unusedInput : [], - overflow : -2, - charsLeftOver : 0, - nullInput : false, - invalidMonth : null, - invalidFormat : false, - userInvalidated : false, - iso: false - }; - } - - function printMsg(msg) { - if (moment.suppressDeprecationWarnings === false && - typeof console !== 'undefined' && console.warn) { - console.warn('Deprecation warning: ' + msg); - } - } - - function deprecate(msg, fn) { - var firstTime = true; - return extend(function () { - if (firstTime) { - printMsg(msg); - firstTime = false; - } - return fn.apply(this, arguments); - }, fn); - } - - function deprecateSimple(name, msg) { - if (!deprecations[name]) { - printMsg(msg); - deprecations[name] = true; - } - } - - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func, period) { - return function (a) { - return this.localeData().ordinal(func.call(this, a), period); - }; - } - - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); - } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); - } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - - - /************************************ - Constructors - ************************************/ - - function Locale() { - } - - // Moment prototype object - function Moment(config, skipOverflow) { - if (skipOverflow !== false) { - checkOverflow(config); - } - copyConfig(this, config); - this._d = new Date(+config._d); - } - - // Duration Constructor - function Duration(duration) { - var normalizedInput = normalizeObjectUnits(duration), - years = normalizedInput.year || 0, - quarters = normalizedInput.quarter || 0, - months = normalizedInput.month || 0, - weeks = normalizedInput.week || 0, - days = normalizedInput.day || 0, - hours = normalizedInput.hour || 0, - minutes = normalizedInput.minute || 0, - seconds = normalizedInput.second || 0, - milliseconds = normalizedInput.millisecond || 0; - - // representation for dateAddRemove - this._milliseconds = +milliseconds + - seconds * 1e3 + // 1000 - minutes * 6e4 + // 1000 * 60 - hours * 36e5; // 1000 * 60 * 60 - // Because of dateAddRemove treats 24 hours as different from a - // day when working around DST, we need to store them separately - this._days = +days + - weeks * 7; - // It is impossible translate months into days without knowing - // which months you are are talking about, so we have to store - // it separately. - this._months = +months + - quarters * 3 + - years * 12; - - this._data = {}; - - this._locale = moment.localeData(); - - this._bubble(); - } - - /************************************ - Helpers - ************************************/ - - - function extend(a, b) { - for (var i in b) { - if (hasOwnProp(b, i)) { - a[i] = b[i]; - } - } - - if (hasOwnProp(b, 'toString')) { - a.toString = b.toString; - } - - if (hasOwnProp(b, 'valueOf')) { - a.valueOf = b.valueOf; - } - - return a; - } - - function copyConfig(to, from) { - var i, prop, val; - - if (typeof from._isAMomentObject !== 'undefined') { - to._isAMomentObject = from._isAMomentObject; - } - if (typeof from._i !== 'undefined') { - to._i = from._i; - } - if (typeof from._f !== 'undefined') { - to._f = from._f; - } - if (typeof from._l !== 'undefined') { - to._l = from._l; - } - if (typeof from._strict !== 'undefined') { - to._strict = from._strict; - } - if (typeof from._tzm !== 'undefined') { - to._tzm = from._tzm; - } - if (typeof from._isUTC !== 'undefined') { - to._isUTC = from._isUTC; - } - if (typeof from._offset !== 'undefined') { - to._offset = from._offset; - } - if (typeof from._pf !== 'undefined') { - to._pf = from._pf; - } - if (typeof from._locale !== 'undefined') { - to._locale = from._locale; - } - - if (momentProperties.length > 0) { - for (i in momentProperties) { - prop = momentProperties[i]; - val = from[prop]; - if (typeof val !== 'undefined') { - to[prop] = val; - } - } - } - - return to; - } - - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } - } - - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength, forceSign) { - var output = '' + Math.abs(number), - sign = number >= 0; - - while (output.length < targetLength) { - output = '0' + output; - } - return (sign ? (forceSign ? '+' : '') : '-') + output; - } - - function positiveMomentsDifference(base, other) { - var res = {milliseconds: 0, months: 0}; - - res.months = other.month() - base.month() + - (other.year() - base.year()) * 12; - if (base.clone().add(res.months, 'M').isAfter(other)) { - --res.months; - } - - res.milliseconds = +other - +(base.clone().add(res.months, 'M')); - - return res; - } - - function momentsDifference(base, other) { - var res; - other = makeAs(other, base); - if (base.isBefore(other)) { - res = positiveMomentsDifference(base, other); - } else { - res = positiveMomentsDifference(other, base); - res.milliseconds = -res.milliseconds; - res.months = -res.months; - } - - return res; - } - - // TODO: remove 'name' arg after deprecation is removed - function createAdder(direction, name) { - return function (val, period) { - var dur, tmp; - //invert the arguments, but complain about it - if (period !== null && !isNaN(+period)) { - deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); - tmp = val; val = period; period = tmp; - } - - val = typeof val === 'string' ? +val : val; - dur = moment.duration(val, period); - addOrSubtractDurationFromMoment(this, dur, direction); - return this; - }; - } - - function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { - var milliseconds = duration._milliseconds, - days = duration._days, - months = duration._months; - updateOffset = updateOffset == null ? true : updateOffset; - - if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); - } - if (days) { - rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); - } - if (months) { - rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); - } - if (updateOffset) { - moment.updateOffset(mom, days || months); - } - } - - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; - } - - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || - input instanceof Date; - } - - // compare two arrays, return the number of differences - function compareArrays(array1, array2, dontConvert) { - var len = Math.min(array1.length, array2.length), - lengthDiff = Math.abs(array1.length - array2.length), - diffs = 0, - i; - for (i = 0; i < len; i++) { - if ((dontConvert && array1[i] !== array2[i]) || - (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { - diffs++; - } - } - return diffs + lengthDiff; - } - - function normalizeUnits(units) { - if (units) { - var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); - units = unitAliases[units] || camelFunctions[lowered] || lowered; - } - return units; - } - - function normalizeObjectUnits(inputObject) { - var normalizedInput = {}, - normalizedProp, - prop; - - for (prop in inputObject) { - if (hasOwnProp(inputObject, prop)) { - normalizedProp = normalizeUnits(prop); - if (normalizedProp) { - normalizedInput[normalizedProp] = inputObject[prop]; - } - } - } - - return normalizedInput; - } - - function makeList(field) { - var count, setter; - - if (field.indexOf('week') === 0) { - count = 7; - setter = 'day'; - } - else if (field.indexOf('month') === 0) { - count = 12; - setter = 'month'; - } - else { - return; - } - - moment[field] = function (format, index) { - var i, getter, - method = moment._locale[field], - results = []; - - if (typeof format === 'number') { - index = format; - format = undefined; - } - - getter = function (i) { - var m = moment().utc().set(setter, i); - return method.call(moment._locale, m, format || ''); - }; - - if (index != null) { - return getter(index); - } - else { - for (i = 0; i < count; i++) { - results.push(getter(i)); - } - return results; - } - }; - } - - function toInt(argumentForCoercion) { - var coercedNumber = +argumentForCoercion, - value = 0; - - if (coercedNumber !== 0 && isFinite(coercedNumber)) { - if (coercedNumber >= 0) { - value = Math.floor(coercedNumber); - } else { - value = Math.ceil(coercedNumber); - } - } - - return value; - } - - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); - } - - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; - } - - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; - } - - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; - } - - function checkOverflow(m) { - var overflow; - if (m._a && m._pf.overflow === -2) { - overflow = - m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : - m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : - m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : - m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : - m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : - m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : - -1; - - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } - - m._pf.overflow = overflow; - } - } - - function isValid(m) { - if (m._isValid == null) { - m._isValid = !isNaN(m._d.getTime()) && - m._pf.overflow < 0 && - !m._pf.empty && - !m._pf.invalidMonth && - !m._pf.nullInput && - !m._pf.invalidFormat && - !m._pf.userInvalidated; - - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0; - } - } - return m._isValid; - } - - function normalizeLocale(key) { - return key ? key.toLowerCase().replace('_', '-') : key; - } - - // pick the locale from the array - // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each - // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root - function chooseLocale(names) { - var i = 0, j, next, locale, split; - - while (i < names.length) { - split = normalizeLocale(names[i]).split('-'); - j = split.length; - next = normalizeLocale(names[i + 1]); - next = next ? next.split('-') : null; - while (j > 0) { - locale = loadLocale(split.slice(0, j).join('-')); - if (locale) { - return locale; - } - if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { - //the next array item is better than a shallower substring of this one - break; - } - j--; - } - i++; - } - return null; - } - - function loadLocale(name) { - var oldLocale = null; - if (!locales[name] && hasModule) { - try { - oldLocale = moment.locale(); - require('./locale/' + name); - // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales - moment.locale(oldLocale); - } catch (e) { } - } - return locales[name]; - } - - // Return a moment from input, that is local/utc/zone equivalent to model. - function makeAs(input, model) { - return model._isUTC ? moment(input).zone(model._offset || 0) : - moment(input).local(); - } - - /************************************ - Locale - ************************************/ - - - extend(Locale.prototype, { - - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - }, - - _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - months : function (m) { - return this._months[m.month()]; - }, - - _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, - - monthsParse : function (monthName) { - var i, mom, regex; - - if (!this._monthsParse) { - this._monthsParse = []; - } - - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - if (!this._monthsParse[i]) { - mom = moment.utc([2000, i]); - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._monthsParse[i].test(monthName)) { - return i; - } - } - }, - - _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, - - _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, - - _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, - - weekdaysParse : function (weekdayName) { - var i, mom, regex; - - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } - - for (i = 0; i < 7; i++) { - // make the regex if we don't have it already - if (!this._weekdaysParse[i]) { - mom = moment([2000, 1]).day(i); - regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); - this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (this._weekdaysParse[i].test(weekdayName)) { - return i; - } - } - }, - - _longDateFormat : { - LT : 'h:mm A', - L : 'MM/DD/YYYY', - LL : 'MMMM D, YYYY', - LLL : 'MMMM D, YYYY LT', - LLLL : 'dddd, MMMM D, YYYY LT' - }, - longDateFormat : function (key) { - var output = this._longDateFormat[key]; - if (!output && this._longDateFormat[key.toUpperCase()]) { - output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { - return val.slice(1); - }); - this._longDateFormat[key] = output; - } - return output; - }, - - isPM : function (input) { - // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays - // Using charAt should be more compatible. - return ((input + '').toLowerCase().charAt(0) === 'p'); - }, - - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, - - _calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom) : output; - }, - - _relativeTime : { - future : 'in %s', - past : '%s ago', - s : 'a few seconds', - m : 'a minute', - mm : '%d minutes', - h : 'an hour', - hh : '%d hours', - d : 'a day', - dd : '%d days', - M : 'a month', - MM : '%d months', - y : 'a year', - yy : '%d years' - }, - - relativeTime : function (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); - }, - - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, - - ordinal : function (number) { - return this._ordinal.replace('%d', number); - }, - _ordinal : '%d', - - preparse : function (string) { - return string; - }, - - postformat : function (string) { - return string; - }, - - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy).week; - }, - - _week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - }, - - _invalidDate: 'Invalid date', - invalidDate: function () { - return this._invalidDate; - } - }); - - /************************************ - Formatting - ************************************/ - - - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ''); - } - return input.replace(/\\/g, ''); - } - - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; - - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } - - return function (mom) { - var output = ''; - for (i = 0; i < length; i++) { - output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; - } - return output; - }; - } - - // format date using native date object - function formatMoment(m, format) { - if (!m.isValid()) { - return m.localeData().invalidDate(); - } - - format = expandFormat(format, m.localeData()); - - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } - - return formatFunctions[format](m); - } - - function expandFormat(format, locale) { - var i = 5; - - function replaceLongDateFormatTokens(input) { - return locale.longDateFormat(input) || input; - } - - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } - - return format; - } - - - /************************************ - Parsing - ************************************/ - - - // get the regex to find the next token - function getParseRegexForToken(token, config) { - var a, strict = config._strict; - switch (token) { - case 'Q': - return parseTokenOneDigit; - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - case 'GGGG': - case 'gggg': - return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; - case 'Y': - case 'G': - case 'g': - return parseTokenSignedNumber; - case 'YYYYYY': - case 'YYYYY': - case 'GGGGG': - case 'ggggg': - return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; - case 'S': - if (strict) { - return parseTokenOneDigit; - } - /* falls through */ - case 'SS': - if (strict) { - return parseTokenTwoDigits; - } - /* falls through */ - case 'SSS': - if (strict) { - return parseTokenThreeDigits; - } - /* falls through */ - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - return parseTokenWord; - case 'a': - case 'A': - return config._locale._meridiemParse; - case 'X': - return parseTokenTimestampMs; - case 'Z': - case 'ZZ': - return parseTokenTimezone; - case 'T': - return parseTokenT; - case 'SSSS': - return parseTokenDigits; - case 'MM': - case 'DD': - case 'YY': - case 'GG': - case 'gg': - case 'HH': - case 'hh': - case 'mm': - case 'ss': - case 'ww': - case 'WW': - return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; - case 'M': - case 'D': - case 'd': - case 'H': - case 'h': - case 'm': - case 's': - case 'w': - case 'W': - case 'e': - case 'E': - return parseTokenOneOrTwoDigits; - case 'Do': - return parseTokenOrdinal; - default : - a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); - return a; - } - } - - function timezoneMinutesFromString(string) { - string = string || ''; - var possibleTzMatches = (string.match(parseTokenTimezone) || []), - tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], - parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], - minutes = +(parts[1] * 60) + toInt(parts[2]); - - return parts[0] === '+' ? -minutes : minutes; - } - - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, datePartArray = config._a; - - switch (token) { - // QUARTER - case 'Q': - if (input != null) { - datePartArray[MONTH] = (toInt(input) - 1) * 3; - } - break; - // MONTH - case 'M' : // fall through to MM - case 'MM' : - if (input != null) { - datePartArray[MONTH] = toInt(input) - 1; - } - break; - case 'MMM' : // fall through to MMMM - case 'MMMM' : - a = config._locale.monthsParse(input); - // if we didn't find a month name, mark the date as invalid. - if (a != null) { - datePartArray[MONTH] = a; - } else { - config._pf.invalidMonth = input; - } - break; - // DAY OF MONTH - case 'D' : // fall through to DD - case 'DD' : - if (input != null) { - datePartArray[DATE] = toInt(input); - } - break; - case 'Do' : - if (input != null) { - datePartArray[DATE] = toInt(parseInt(input, 10)); - } - break; - // DAY OF YEAR - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - config._dayOfYear = toInt(input); - } - - break; - // YEAR - case 'YY' : - datePartArray[YEAR] = moment.parseTwoDigitYear(input); - break; - case 'YYYY' : - case 'YYYYY' : - case 'YYYYYY' : - datePartArray[YEAR] = toInt(input); - break; - // AM / PM - case 'a' : // fall through to A - case 'A' : - config._isPm = config._locale.isPM(input); - break; - // 24 HOUR - case 'H' : // fall through to hh - case 'HH' : // fall through to hh - case 'h' : // fall through to hh - case 'hh' : - datePartArray[HOUR] = toInt(input); - break; - // MINUTE - case 'm' : // fall through to mm - case 'mm' : - datePartArray[MINUTE] = toInt(input); - break; - // SECOND - case 's' : // fall through to ss - case 'ss' : - datePartArray[SECOND] = toInt(input); - break; - // MILLISECOND - case 'S' : - case 'SS' : - case 'SSS' : - case 'SSSS' : - datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); - break; - // UNIX TIMESTAMP WITH MS - case 'X': - config._d = new Date(parseFloat(input) * 1000); - break; - // TIMEZONE - case 'Z' : // fall through to ZZ - case 'ZZ' : - config._useUTC = true; - config._tzm = timezoneMinutesFromString(input); - break; - // WEEKDAY - human - case 'dd': - case 'ddd': - case 'dddd': - a = config._locale.weekdaysParse(input); - // if we didn't get a weekday name, mark the date as invalid - if (a != null) { - config._w = config._w || {}; - config._w['d'] = a; - } else { - config._pf.invalidWeekday = input; - } - break; - // WEEK, WEEK DAY - numeric - case 'w': - case 'ww': - case 'W': - case 'WW': - case 'd': - case 'e': - case 'E': - token = token.substr(0, 1); - /* falls through */ - case 'gggg': - case 'GGGG': - case 'GGGGG': - token = token.substr(0, 2); - if (input) { - config._w = config._w || {}; - config._w[token] = toInt(input); - } - break; - case 'gg': - case 'GG': - config._w = config._w || {}; - config._w[token] = moment.parseTwoDigitYear(input); - } - } - - function dayOfYearFromWeekInfo(config) { - var w, weekYear, week, weekday, dow, doy, temp; - - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - dow = 1; - doy = 4; - - // TODO: We need to take the current isoWeekYear, but that depends on - // how we interpret now (local, utc, fixed offset). So create - // a now version of current config (take local/utc/offset flags, and - // create now). - weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year); - week = dfl(w.W, 1); - weekday = dfl(w.E, 1); - } else { - dow = config._locale._week.dow; - doy = config._locale._week.doy; - - weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); - week = dfl(w.w, 1); - - if (w.d != null) { - // weekday -- low day numbers are considered next week - weekday = w.d; - if (weekday < dow) { - ++week; - } - } else if (w.e != null) { - // local weekday -- counting starts from begining of week - weekday = w.e + dow; - } else { - // default to begining of week - weekday = dow; - } - } - temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); - - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; - } - - // convert an array to a date. - // the array should mirror the parameters below - // note: all values past the year are optional and will default to the lowest possible value. - // [year, month, day , hour, minute, second, millisecond] - function dateFromConfig(config) { - var i, date, input = [], currentDate, yearToUse; - - if (config._d) { - return; - } - - currentDate = currentDateArray(config); - - //compute day of the year from weeks and weekdays - if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - dayOfYearFromWeekInfo(config); - } - - //if the day of the year is set, figure out what it is - if (config._dayOfYear) { - yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); - - if (config._dayOfYear > daysInYear(yearToUse)) { - config._pf._overflowDayOfYear = true; - } - - date = makeUTCDate(yearToUse, 0, config._dayOfYear); - config._a[MONTH] = date.getUTCMonth(); - config._a[DATE] = date.getUTCDate(); - } - - // Default to current date. - // * if no year, month, day of month are given, default to today - // * if day of month is given, default month and year - // * if month is given, default only year - // * if year is given, don't default anything - for (i = 0; i < 3 && config._a[i] == null; ++i) { - config._a[i] = input[i] = currentDate[i]; - } - - // Zero out whatever was not defaulted, including time - for (; i < 7; i++) { - config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; - } - - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); - // Apply timezone offset from input. The actual zone can be changed - // with parseZone. - if (config._tzm != null) { - config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm); - } - } - - function dateFromObject(config) { - var normalizedInput; - - if (config._d) { - return; - } - - normalizedInput = normalizeObjectUnits(config._i); - config._a = [ - normalizedInput.year, - normalizedInput.month, - normalizedInput.day, - normalizedInput.hour, - normalizedInput.minute, - normalizedInput.second, - normalizedInput.millisecond - ]; - - dateFromConfig(config); - } - - function currentDateArray(config) { - var now = new Date(); - if (config._useUTC) { - return [ - now.getUTCFullYear(), - now.getUTCMonth(), - now.getUTCDate() - ]; - } else { - return [now.getFullYear(), now.getMonth(), now.getDate()]; - } - } - - // date from string and format string - function makeDateFromStringAndFormat(config) { - if (config._f === moment.ISO_8601) { - parseISO(config); - return; - } - - config._a = []; - config._pf.empty = true; - - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var string = '' + config._i, - i, parsedInput, tokens, token, skipped, - stringLength = string.length, - totalParsedInputLength = 0; - - tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; - - for (i = 0; i < tokens.length; i++) { - token = tokens[i]; - parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; - if (parsedInput) { - skipped = string.substr(0, string.indexOf(parsedInput)); - if (skipped.length > 0) { - config._pf.unusedInput.push(skipped); - } - string = string.slice(string.indexOf(parsedInput) + parsedInput.length); - totalParsedInputLength += parsedInput.length; - } - // don't parse if it's not a known token - if (formatTokenFunctions[token]) { - if (parsedInput) { - config._pf.empty = false; - } - else { - config._pf.unusedTokens.push(token); - } - addTimeToArrayFromToken(token, parsedInput, config); - } - else if (config._strict && !parsedInput) { - config._pf.unusedTokens.push(token); - } - } - - // add remaining unparsed input length to the string - config._pf.charsLeftOver = stringLength - totalParsedInputLength; - if (string.length > 0) { - config._pf.unusedInput.push(string); - } - - // handle am pm - if (config._isPm && config._a[HOUR] < 12) { - config._a[HOUR] += 12; - } - // if is 12 am, change hours to 0 - if (config._isPm === false && config._a[HOUR] === 12) { - config._a[HOUR] = 0; - } - - dateFromConfig(config); - checkOverflow(config); - } - - function unescapeFormat(s) { - return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { - return p1 || p2 || p3 || p4; - }); - } - - // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - function regexpEscape(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } - - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - bestMoment, - - scoreToBeat, - i, - currentScore; - - if (config._f.length === 0) { - config._pf.invalidFormat = true; - config._d = new Date(NaN); - return; - } - - for (i = 0; i < config._f.length; i++) { - currentScore = 0; - tempConfig = copyConfig({}, config); - if (config._useUTC != null) { - tempConfig._useUTC = config._useUTC; - } - tempConfig._pf = defaultParsingFlags(); - tempConfig._f = config._f[i]; - makeDateFromStringAndFormat(tempConfig); - - if (!isValid(tempConfig)) { - continue; - } - - // if there is any input that was not parsed add a penalty for that format - currentScore += tempConfig._pf.charsLeftOver; - - //or tokens - currentScore += tempConfig._pf.unusedTokens.length * 10; - - tempConfig._pf.score = currentScore; - - if (scoreToBeat == null || currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempConfig; - } - } - - extend(config, bestMoment || tempConfig); - } - - // date from iso format - function parseISO(config) { - var i, l, - string = config._i, - match = isoRegex.exec(string); - - if (match) { - config._pf.iso = true; - for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { - // match[5] should be 'T' or undefined - config._f = isoDates[i][0] + (match[6] || ' '); - break; - } - } - for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (string.match(parseTokenTimezone)) { - config._f += 'Z'; - } - makeDateFromStringAndFormat(config); - } else { - config._isValid = false; - } - } - - // date from iso format or fallback - function makeDateFromString(config) { - parseISO(config); - if (config._isValid === false) { - delete config._isValid; - moment.createFromInputFallback(config); - } - } - - function map(arr, fn) { - var res = [], i; - for (i = 0; i < arr.length; ++i) { - res.push(fn(arr[i], i)); - } - return res; - } - - function makeDateFromInput(config) { - var input = config._i, matched; - if (input === undefined) { - config._d = new Date(); - } else if (isDate(input)) { - config._d = new Date(+input); - } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = map(input.slice(0), function (obj) { - return parseInt(obj, 10); - }); - dateFromConfig(config); - } else if (typeof(input) === 'object') { - dateFromObject(config); - } else if (typeof(input) === 'number') { - // from milliseconds - config._d = new Date(input); - } else { - moment.createFromInputFallback(config); - } - } - - function makeDate(y, m, d, h, M, s, ms) { - //can't just apply() to create a date: - //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply - var date = new Date(y, m, d, h, M, s, ms); - - //the date constructor doesn't accept years < 1970 - if (y < 1970) { - date.setFullYear(y); - } - return date; - } - - function makeUTCDate(y) { - var date = new Date(Date.UTC.apply(null, arguments)); - if (y < 1970) { - date.setUTCFullYear(y); - } - return date; - } - - function parseWeekday(input, locale) { - if (typeof input === 'string') { - if (!isNaN(input)) { - input = parseInt(input, 10); - } - else { - input = locale.weekdaysParse(input); - if (typeof input !== 'number') { - return null; - } - } - } - return input; - } - - /************************************ - Relative Time - ************************************/ - - - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { - return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); - } - - function relativeTime(posNegDuration, withoutSuffix, locale) { - var duration = moment.duration(posNegDuration).abs(), - seconds = round(duration.as('s')), - minutes = round(duration.as('m')), - hours = round(duration.as('h')), - days = round(duration.as('d')), - months = round(duration.as('M')), - years = round(duration.as('y')), - - args = seconds < relativeTimeThresholds.s && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < relativeTimeThresholds.m && ['mm', minutes] || - hours === 1 && ['h'] || - hours < relativeTimeThresholds.h && ['hh', hours] || - days === 1 && ['d'] || - days < relativeTimeThresholds.d && ['dd', days] || - months === 1 && ['M'] || - months < relativeTimeThresholds.M && ['MM', months] || - years === 1 && ['y'] || ['yy', years]; - - args[2] = withoutSuffix; - args[3] = +posNegDuration > 0; - args[4] = locale; - return substituteTimeAgo.apply({}, args); - } - - - /************************************ - Week of Year - ************************************/ - - - // firstDayOfWeek 0 = sun, 6 = sat - // the day of the week that starts the week - // (usually sunday or monday) - // firstDayOfWeekOfYear 0 = sun, 6 = sat - // the first week is the week that contains the first - // of this day of the week - // (eg. ISO weeks use thursday (4)) - function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { - var end = firstDayOfWeekOfYear - firstDayOfWeek, - daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), - adjustedMoment; - - - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } - - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } - - adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); - return { - week: Math.ceil(adjustedMoment.dayOfYear() / 7), - year: adjustedMoment.year() - }; - } - - //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday - function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { - var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; - - d = d === 0 ? 7 : d; - weekday = weekday != null ? weekday : firstDayOfWeek; - daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); - dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; - - return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear - }; - } - - /************************************ - Top Level Functions - ************************************/ - - function makeMoment(config) { - var input = config._i, - format = config._f; - - config._locale = config._locale || moment.localeData(config._l); - - if (input === null || (format === undefined && input === '')) { - return moment.invalid({nullInput: true}); - } - - if (typeof input === 'string') { - config._i = input = config._locale.preparse(input); - } - - if (moment.isMoment(input)) { - return new Moment(input, true); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); - } - } else { - makeDateFromInput(config); - } - - return new Moment(config); - } - - moment = function (input, format, locale, strict) { - var c; - - if (typeof(locale) === 'boolean') { - strict = locale; - locale = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._i = input; - c._f = format; - c._l = locale; - c._strict = strict; - c._isUTC = false; - c._pf = defaultParsingFlags(); - - return makeMoment(c); - }; - - moment.suppressDeprecationWarnings = false; - - moment.createFromInputFallback = deprecate( - 'moment construction falls back to js Date. This is ' + - 'discouraged and will be removed in upcoming major ' + - 'release. Please refer to ' + - 'https://github.com/moment/moment/issues/1407 for more info.', - function (config) { - config._d = new Date(config._i); - } - ); - - // Pick a moment m from moments so that m[fn](other) is true for all - // other. This relies on the function fn to be transitive. - // - // moments should either be an array of moment objects or an array, whose - // first element is an array of moment objects. - function pickBy(fn, moments) { - var res, i; - if (moments.length === 1 && isArray(moments[0])) { - moments = moments[0]; - } - if (!moments.length) { - return moment(); - } - res = moments[0]; - for (i = 1; i < moments.length; ++i) { - if (moments[i][fn](res)) { - res = moments[i]; - } - } - return res; - } - - moment.min = function () { - var args = [].slice.call(arguments, 0); - - return pickBy('isBefore', args); - }; - - moment.max = function () { - var args = [].slice.call(arguments, 0); - - return pickBy('isAfter', args); - }; - - // creating with utc - moment.utc = function (input, format, locale, strict) { - var c; - - if (typeof(locale) === 'boolean') { - strict = locale; - locale = undefined; - } - // object construction must be done this way. - // https://github.com/moment/moment/issues/1423 - c = {}; - c._isAMomentObject = true; - c._useUTC = true; - c._isUTC = true; - c._l = locale; - c._i = input; - c._f = format; - c._strict = strict; - c._pf = defaultParsingFlags(); - - return makeMoment(c).utc(); - }; - - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; - - // duration - moment.duration = function (input, key) { - var duration = input, - // matching against regexp is expensive, do it on demand - match = null, - sign, - ret, - parseIso, - diffRes; - - if (moment.isDuration(input)) { - duration = { - ms: input._milliseconds, - d: input._days, - M: input._months - }; - } else if (typeof input === 'number') { - duration = {}; - if (key) { - duration[key] = input; - } else { - duration.milliseconds = input; - } - } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { - sign = (match[1] === '-') ? -1 : 1; - duration = { - y: 0, - d: toInt(match[DATE]) * sign, - h: toInt(match[HOUR]) * sign, - m: toInt(match[MINUTE]) * sign, - s: toInt(match[SECOND]) * sign, - ms: toInt(match[MILLISECOND]) * sign - }; - } else if (!!(match = isoDurationRegex.exec(input))) { - sign = (match[1] === '-') ? -1 : 1; - parseIso = function (inp) { - // We'd normally use ~~inp for this, but unfortunately it also - // converts floats to ints. - // inp may be undefined, so careful calling replace on it. - var res = inp && parseFloat(inp.replace(',', '.')); - // apply sign while we're at it - return (isNaN(res) ? 0 : res) * sign; - }; - duration = { - y: parseIso(match[2]), - M: parseIso(match[3]), - d: parseIso(match[4]), - h: parseIso(match[5]), - m: parseIso(match[6]), - s: parseIso(match[7]), - w: parseIso(match[8]) - }; - } else if (typeof duration === 'object' && - ('from' in duration || 'to' in duration)) { - diffRes = momentsDifference(moment(duration.from), moment(duration.to)); - - duration = {}; - duration.ms = diffRes.milliseconds; - duration.M = diffRes.months; - } - - ret = new Duration(duration); - - if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { - ret._locale = input._locale; - } - - return ret; - }; - - // version number - moment.version = VERSION; - - // default format - moment.defaultFormat = isoFormat; - - // constant that refers to the ISO standard - moment.ISO_8601 = function () {}; - - // Plugins that add properties should also add the key here (null value), - // so we can properly clone ourselves. - moment.momentProperties = momentProperties; - - // This function will be called whenever a moment is mutated. - // It is intended to keep the offset in sync with the timezone. - moment.updateOffset = function () {}; - - // This function allows you to set a threshold for relative time strings - moment.relativeTimeThreshold = function (threshold, limit) { - if (relativeTimeThresholds[threshold] === undefined) { - return false; - } - if (limit === undefined) { - return relativeTimeThresholds[threshold]; - } - relativeTimeThresholds[threshold] = limit; - return true; - }; - - moment.lang = deprecate( - 'moment.lang is deprecated. Use moment.locale instead.', - function (key, value) { - return moment.locale(key, value); - } - ); - - // This function will load locale and then set the global locale. If - // no arguments are passed in, it will simply return the current global - // locale key. - moment.locale = function (key, values) { - var data; - if (key) { - if (typeof(values) !== 'undefined') { - data = moment.defineLocale(key, values); - } - else { - data = moment.localeData(key); - } - - if (data) { - moment.duration._locale = moment._locale = data; - } - } - - return moment._locale._abbr; - }; - - moment.defineLocale = function (name, values) { - if (values !== null) { - values.abbr = name; - if (!locales[name]) { - locales[name] = new Locale(); - } - locales[name].set(values); - - // backwards compat for now: also set the locale - moment.locale(name); - - return locales[name]; - } else { - // useful for testing - delete locales[name]; - return null; - } - }; - - moment.langData = deprecate( - 'moment.langData is deprecated. Use moment.localeData instead.', - function (key) { - return moment.localeData(key); - } - ); - - // returns locale data - moment.localeData = function (key) { - var locale; - - if (key && key._locale && key._locale._abbr) { - key = key._locale._abbr; - } - - if (!key) { - return moment._locale; - } - - if (!isArray(key)) { - //short-circuit everything else - locale = loadLocale(key); - if (locale) { - return locale; - } - key = [key]; - } - - return chooseLocale(key); - }; - - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment || - (obj != null && hasOwnProp(obj, '_isAMomentObject')); - }; - - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; - - for (i = lists.length - 1; i >= 0; --i) { - makeList(lists[i]); - } - - moment.normalizeUnits = function (units) { - return normalizeUnits(units); - }; - - moment.invalid = function (flags) { - var m = moment.utc(NaN); - if (flags != null) { - extend(m._pf, flags); - } - else { - m._pf.userInvalidated = true; - } - - return m; - }; - - moment.parseZone = function () { - return moment.apply(null, arguments).parseZone(); - }; - - moment.parseTwoDigitYear = function (input) { - return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); - }; - - /************************************ - Moment Prototype - ************************************/ - - - extend(moment.fn = Moment.prototype, { - - clone : function () { - return moment(this); - }, - - valueOf : function () { - return +this._d + ((this._offset || 0) * 60000); - }, - - unix : function () { - return Math.floor(+this / 1000); - }, - - toString : function () { - return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); - }, - - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, - - toISOString : function () { - var m = moment(this).utc(); - if (0 < m.year() && m.year() <= 9999) { - return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } else { - return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); - } - }, - - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, - - isValid : function () { - return isValid(this); - }, - - isDSTShifted : function () { - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } - - return false; - }, - - parsingFlags : function () { - return extend({}, this._pf); - }, - - invalidAt: function () { - return this._pf.overflow; - }, - - utc : function (keepLocalTime) { - return this.zone(0, keepLocalTime); - }, - - local : function (keepLocalTime) { - if (this._isUTC) { - this.zone(0, keepLocalTime); - this._isUTC = false; - - if (keepLocalTime) { - this.add(this._dateTzOffset(), 'm'); - } - } - return this; - }, - - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.localeData().postformat(output); - }, - - add : createAdder(1, 'add'), - - subtract : createAdder(-1, 'subtract'), - - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output, daysAdjust; - - units = normalizeUnits(units); - - if (units === 'year' || units === 'month') { - // average number of days in the months in the given dates - diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 - // difference in months - output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); - // adjust by taking difference in days, average number of days - // and dst in the given months. - daysAdjust = (this - moment(this).startOf('month')) - - (that - moment(that).startOf('month')); - // same as above but with zones, to negate all dst - daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) - - (that.zone() - moment(that).startOf('month').zone())) * 6e4; - output += daysAdjust / diff; - if (units === 'year') { - output = output / 12; - } - } else { - diff = (this - that); - output = units === 'second' ? diff / 1e3 : // 1000 - units === 'minute' ? diff / 6e4 : // 1000 * 60 - units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 - units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst - units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst - diff; - } - return asFloat ? output : absRound(output); - }, - - from : function (time, withoutSuffix) { - return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); - }, - - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, - - calendar : function (time) { - // We want to compare the start of today, vs this. - // Getting start-of-today depends on whether we're zone'd or not. - var now = time || moment(), - sod = makeAs(now, this).startOf('day'), - diff = this.diff(sod, 'days', true), - format = diff < -6 ? 'sameElse' : - diff < -1 ? 'lastWeek' : - diff < 0 ? 'lastDay' : - diff < 1 ? 'sameDay' : - diff < 2 ? 'nextDay' : - diff < 7 ? 'nextWeek' : 'sameElse'; - return this.format(this.localeData().calendar(format, this)); - }, - - isLeapYear : function () { - return isLeapYear(this.year()); - }, - - isDST : function () { - return (this.zone() < this.clone().month(0).zone() || - this.zone() < this.clone().month(5).zone()); - }, - - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - if (input != null) { - input = parseWeekday(input, this.localeData()); - return this.add(input - day, 'd'); - } else { - return day; - } - }, - - month : makeAccessor('Month', true), - - startOf : function (units) { - units = normalizeUnits(units); - // the following switch intentionally omits break keywords - // to utilize falling through the cases. - switch (units) { - case 'year': - this.month(0); - /* falls through */ - case 'quarter': - case 'month': - this.date(1); - /* falls through */ - case 'week': - case 'isoWeek': - case 'day': - this.hours(0); - /* falls through */ - case 'hour': - this.minutes(0); - /* falls through */ - case 'minute': - this.seconds(0); - /* falls through */ - case 'second': - this.milliseconds(0); - /* falls through */ - } - - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } - - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } - - return this; - }, - - endOf: function (units) { - units = normalizeUnits(units); - return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); - }, - - isAfter: function (input, units) { - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this > +input; - } else { - return +this.clone().startOf(units) > +moment(input).startOf(units); - } - }, - - isBefore: function (input, units) { - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this < +input; - } else { - return +this.clone().startOf(units) < +moment(input).startOf(units); - } - }, - - isSame: function (input, units) { - units = normalizeUnits(units || 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this === +input; - } else { - return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); - } - }, - - min: deprecate( - 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', - function (other) { - other = moment.apply(null, arguments); - return other < this ? this : other; - } - ), - - max: deprecate( - 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', - function (other) { - other = moment.apply(null, arguments); - return other > this ? this : other; - } - ), - - // keepLocalTime = true means only change the timezone, without - // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]--> - // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone - // +0200, so we adjust the time as needed, to be valid. - // - // Keeping the time actually adds/subtracts (one hour) - // from the actual represented time. That is why we call updateOffset - // a second time. In case it wants us to change the offset again - // _changeInProgress == true case, then we have to adjust, because - // there is no such time in the given timezone. - zone : function (input, keepLocalTime) { - var offset = this._offset || 0, - localAdjust; - if (input != null) { - if (typeof input === 'string') { - input = timezoneMinutesFromString(input); - } - if (Math.abs(input) < 16) { - input = input * 60; - } - if (!this._isUTC && keepLocalTime) { - localAdjust = this._dateTzOffset(); - } - this._offset = input; - this._isUTC = true; - if (localAdjust != null) { - this.subtract(localAdjust, 'm'); - } - if (offset !== input) { - if (!keepLocalTime || this._changeInProgress) { - addOrSubtractDurationFromMoment(this, - moment.duration(offset - input, 'm'), 1, false); - } else if (!this._changeInProgress) { - this._changeInProgress = true; - moment.updateOffset(this, true); - this._changeInProgress = null; - } - } - } else { - return this._isUTC ? offset : this._dateTzOffset(); - } - return this; - }, - - zoneAbbr : function () { - return this._isUTC ? 'UTC' : ''; - }, - - zoneName : function () { - return this._isUTC ? 'Coordinated Universal Time' : ''; - }, - - parseZone : function () { - if (this._tzm) { - this.zone(this._tzm); - } else if (typeof this._i === 'string') { - this.zone(this._i); - } - return this; - }, - - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).zone(); - } - - return (this.zone() - input) % 60 === 0; - }, - - daysInMonth : function () { - return daysInMonth(this.year(), this.month()); - }, - - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); - }, - - quarter : function (input) { - return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); - }, - - weekYear : function (input) { - var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; - return input == null ? year : this.add((input - year), 'y'); - }, - - isoWeekYear : function (input) { - var year = weekOfYear(this, 1, 4).year; - return input == null ? year : this.add((input - year), 'y'); - }, - - week : function (input) { - var week = this.localeData().week(this); - return input == null ? week : this.add((input - week) * 7, 'd'); - }, - - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4).week; - return input == null ? week : this.add((input - week) * 7, 'd'); - }, - - weekday : function (input) { - var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; - return input == null ? weekday : this.add(input - weekday, 'd'); - }, - - isoWeekday : function (input) { - // behaves the same as moment#day except - // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) - // as a setter, sunday should belong to the previous week. - return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); - }, - - isoWeeksInYear : function () { - return weeksInYear(this.year(), 1, 4); - }, - - weeksInYear : function () { - var weekInfo = this.localeData()._week; - return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); - }, - - get : function (units) { - units = normalizeUnits(units); - return this[units](); - }, - - set : function (units, value) { - units = normalizeUnits(units); - if (typeof this[units] === 'function') { - this[units](value); - } - return this; - }, - - // If passed a locale key, it will set the locale for this - // instance. Otherwise, it will return the locale configuration - // variables for this instance. - locale : function (key) { - var newLocaleData; - - if (key === undefined) { - return this._locale._abbr; - } else { - newLocaleData = moment.localeData(key); - if (newLocaleData != null) { - this._locale = newLocaleData; - } - return this; - } - }, - - lang : deprecate( - 'moment().lang() is deprecated. Use moment().localeData() instead.', - function (key) { - if (key === undefined) { - return this.localeData(); - } else { - return this.locale(key); - } - } - ), - - localeData : function () { - return this._locale; - }, - - _dateTzOffset : function () { - // On Firefox.24 Date#getTimezoneOffset returns a floating point. - // https://github.com/moment/moment/pull/1871 - return Math.round(this._d.getTimezoneOffset() / 15) * 15; - } - }); - - function rawMonthSetter(mom, value) { - var dayOfMonth; - - // TODO: Move this out of here! - if (typeof value === 'string') { - value = mom.localeData().monthsParse(value); - // TODO: Another silent failure? - if (typeof value !== 'number') { - return mom; - } - } - - dayOfMonth = Math.min(mom.date(), - daysInMonth(mom.year(), value)); - mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); - return mom; - } - - function rawGetter(mom, unit) { - return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); - } - - function rawSetter(mom, unit, value) { - if (unit === 'Month') { - return rawMonthSetter(mom, value); - } else { - return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); - } - } - - function makeAccessor(unit, keepTime) { - return function (value) { - if (value != null) { - rawSetter(this, unit, value); - moment.updateOffset(this, keepTime); - return this; - } else { - return rawGetter(this, unit); - } - }; - } - - moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); - moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); - moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); - // Setting the hour should keep the time, because the user explicitly - // specified which hour he wants. So trying to maintain the same hour (in - // a new timezone) makes sense. Adding/subtracting hours does not follow - // this rule. - moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); - // moment.fn.month is defined separately - moment.fn.date = makeAccessor('Date', true); - moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true)); - moment.fn.year = makeAccessor('FullYear', true); - moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true)); - - // add plural methods - moment.fn.days = moment.fn.day; - moment.fn.months = moment.fn.month; - moment.fn.weeks = moment.fn.week; - moment.fn.isoWeeks = moment.fn.isoWeek; - moment.fn.quarters = moment.fn.quarter; - - // add aliased format methods - moment.fn.toJSON = moment.fn.toISOString; - - /************************************ - Duration Prototype - ************************************/ - - - function daysToYears (days) { - // 400 years have 146097 days (taking into account leap year rules) - return days * 400 / 146097; - } - - function yearsToDays (years) { - // years * 365 + absRound(years / 4) - - // absRound(years / 100) + absRound(years / 400); - return years * 146097 / 400; - } - - extend(moment.duration.fn = Duration.prototype, { - - _bubble : function () { - var milliseconds = this._milliseconds, - days = this._days, - months = this._months, - data = this._data, - seconds, minutes, hours, years = 0; - - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; - - seconds = absRound(milliseconds / 1000); - data.seconds = seconds % 60; - - minutes = absRound(seconds / 60); - data.minutes = minutes % 60; - - hours = absRound(minutes / 60); - data.hours = hours % 24; - - days += absRound(hours / 24); - - // Accurately convert days to years, assume start from year 0. - years = absRound(daysToYears(days)); - days -= absRound(yearsToDays(years)); - - // 30 days to a month - // TODO (iskren): Use anchor date (like 1st Jan) to compute this. - months += absRound(days / 30); - days %= 30; - - // 12 months -> 1 year - years += absRound(months / 12); - months %= 12; - - data.days = days; - data.months = months; - data.years = years; - }, - - abs : function () { - this._milliseconds = Math.abs(this._milliseconds); - this._days = Math.abs(this._days); - this._months = Math.abs(this._months); - - this._data.milliseconds = Math.abs(this._data.milliseconds); - this._data.seconds = Math.abs(this._data.seconds); - this._data.minutes = Math.abs(this._data.minutes); - this._data.hours = Math.abs(this._data.hours); - this._data.months = Math.abs(this._data.months); - this._data.years = Math.abs(this._data.years); - - return this; - }, - - weeks : function () { - return absRound(this.days() / 7); - }, - - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6; - }, - - humanize : function (withSuffix) { - var output = relativeTime(this, !withSuffix, this.localeData()); - - if (withSuffix) { - output = this.localeData().pastFuture(+this, output); - } - - return this.localeData().postformat(output); - }, - - add : function (input, val) { - // supports only 2.0-style add(1, 's') or add(moment) - var dur = moment.duration(input, val); - - this._milliseconds += dur._milliseconds; - this._days += dur._days; - this._months += dur._months; - - this._bubble(); - - return this; - }, - - subtract : function (input, val) { - var dur = moment.duration(input, val); - - this._milliseconds -= dur._milliseconds; - this._days -= dur._days; - this._months -= dur._months; - - this._bubble(); - - return this; - }, - - get : function (units) { - units = normalizeUnits(units); - return this[units.toLowerCase() + 's'](); - }, - - as : function (units) { - var days, months; - units = normalizeUnits(units); - - if (units === 'month' || units === 'year') { - days = this._days + this._milliseconds / 864e5; - months = this._months + daysToYears(days) * 12; - return units === 'month' ? months : months / 12; - } else { - // handle milliseconds separately because of floating point math errors (issue #1867) - days = this._days + yearsToDays(this._months / 12); - switch (units) { - case 'week': return days / 7 + this._milliseconds / 6048e5; - case 'day': return days + this._milliseconds / 864e5; - case 'hour': return days * 24 + this._milliseconds / 36e5; - case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; - case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; - // Math.floor prevents floating point math errors here - case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; - default: throw new Error('Unknown unit ' + units); - } - } - }, - - lang : moment.fn.lang, - locale : moment.fn.locale, - - toIsoString : deprecate( - 'toIsoString() is deprecated. Please use toISOString() instead ' + - '(notice the capitals)', - function () { - return this.toISOString(); - } - ), - - toISOString : function () { - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var years = Math.abs(this.years()), - months = Math.abs(this.months()), - days = Math.abs(this.days()), - hours = Math.abs(this.hours()), - minutes = Math.abs(this.minutes()), - seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); - - if (!this.asSeconds()) { - // this is the same as C#'s (Noda) and python (isodate)... - // but not other JS (goog.date) - return 'P0D'; - } - - return (this.asSeconds() < 0 ? '-' : '') + - 'P' + - (years ? years + 'Y' : '') + - (months ? months + 'M' : '') + - (days ? days + 'D' : '') + - ((hours || minutes || seconds) ? 'T' : '') + - (hours ? hours + 'H' : '') + - (minutes ? minutes + 'M' : '') + - (seconds ? seconds + 'S' : ''); - }, - - localeData : function () { - return this._locale; - } - }); - - moment.duration.fn.toString = moment.duration.fn.toISOString; - - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; - } - - for (i in unitMillisecondFactors) { - if (hasOwnProp(unitMillisecondFactors, i)) { - makeDurationGetter(i.toLowerCase()); - } - } - - moment.duration.fn.asMilliseconds = function () { - return this.as('ms'); - }; - moment.duration.fn.asSeconds = function () { - return this.as('s'); - }; - moment.duration.fn.asMinutes = function () { - return this.as('m'); - }; - moment.duration.fn.asHours = function () { - return this.as('h'); - }; - moment.duration.fn.asDays = function () { - return this.as('d'); - }; - moment.duration.fn.asWeeks = function () { - return this.as('weeks'); - }; - moment.duration.fn.asMonths = function () { - return this.as('M'); - }; - moment.duration.fn.asYears = function () { - return this.as('y'); - }; - - /************************************ - Default Locale - ************************************/ - - - // Set default locale, other locale will inherit from English. - moment.locale('en', { - ordinal : function (number) { - var b = number % 10, - output = (toInt(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); - - // moment.js locale configuration -// locale : afrikaans (af) -// author : Werner Mollentze : https://github.com/wernerm - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('af', { - months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), - monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), - weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), - weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), - weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), - meridiem : function (hours, minutes, isLower) { - if (hours < 12) { - return isLower ? 'vm' : 'VM'; - } else { - return isLower ? 'nm' : 'NM'; - } - }, - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Vandag om] LT', - nextDay : '[Môre om] LT', - nextWeek : 'dddd [om] LT', - lastDay : '[Gister om] LT', - lastWeek : '[Laas] dddd [om] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'oor %s', - past : '%s gelede', - s : '\'n paar sekondes', - m : '\'n minuut', - mm : '%d minute', - h : '\'n uur', - hh : '%d ure', - d : '\'n dag', - dd : '%d dae', - M : '\'n maand', - MM : '%d maande', - y : '\'n jaar', - yy : '%d jaar' - }, - ordinal : function (number) { - return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter - }, - week : { - dow : 1, // Maandag is die eerste dag van die week. - doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. - } - }); -})); -// moment.js locale configuration -// locale : Moroccan Arabic (ar-ma) -// author : ElFadili Yassine : https://github.com/ElFadiliY -// author : Abdel Said : https://github.com/abdelsaid - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ar-ma', { - months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), - monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), - weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), - weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), - weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[اليوم على الساعة] LT', - nextDay: '[غدا على الساعة] LT', - nextWeek: 'dddd [على الساعة] LT', - lastDay: '[أمس على الساعة] LT', - lastWeek: 'dddd [على الساعة] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'في %s', - past : 'منذ %s', - s : 'ثوان', - m : 'دقيقة', - mm : '%d دقائق', - h : 'ساعة', - hh : '%d ساعات', - d : 'يوم', - dd : '%d أيام', - M : 'شهر', - MM : '%d أشهر', - y : 'سنة', - yy : '%d سنوات' - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Arabic Saudi Arabia (ar-sa) -// author : Suhail Alkowaileet : https://github.com/xsoh - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '١', - '2': '٢', - '3': '٣', - '4': '٤', - '5': '٥', - '6': '٦', - '7': '٧', - '8': '٨', - '9': '٩', - '0': '٠' - }, numberMap = { - '١': '1', - '٢': '2', - '٣': '3', - '٤': '4', - '٥': '5', - '٦': '6', - '٧': '7', - '٨': '8', - '٩': '9', - '٠': '0' - }; - - return moment.defineLocale('ar-sa', { - months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), - monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), - weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), - weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), - weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return 'ص'; - } else { - return 'م'; - } - }, - calendar : { - sameDay: '[اليوم على الساعة] LT', - nextDay: '[غدا على الساعة] LT', - nextWeek: 'dddd [على الساعة] LT', - lastDay: '[أمس على الساعة] LT', - lastWeek: 'dddd [على الساعة] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'في %s', - past : 'منذ %s', - s : 'ثوان', - m : 'دقيقة', - mm : '%d دقائق', - h : 'ساعة', - hh : '%d ساعات', - d : 'يوم', - dd : '%d أيام', - M : 'شهر', - MM : '%d أشهر', - y : 'سنة', - yy : '%d سنوات' - }, - preparse: function (string) { - return string.replace(/[۰-۹]/g, function (match) { - return numberMap[match]; - }).replace(/،/g, ','); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }).replace(/,/g, '،'); - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// Locale: Arabic (ar) -// Author: Abdel Said: https://github.com/abdelsaid -// Changes in months, weekdays: Ahmed Elkhatib -// Native plural forms: forabi https://github.com/forabi - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '١', - '2': '٢', - '3': '٣', - '4': '٤', - '5': '٥', - '6': '٦', - '7': '٧', - '8': '٨', - '9': '٩', - '0': '٠' - }, numberMap = { - '١': '1', - '٢': '2', - '٣': '3', - '٤': '4', - '٥': '5', - '٦': '6', - '٧': '7', - '٨': '8', - '٩': '9', - '٠': '0' - }, pluralForm = function (n) { - return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; - }, plurals = { - s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], - m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], - h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], - d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], - M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], - y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] - }, pluralize = function (u) { - return function (number, withoutSuffix, string, isFuture) { - var f = pluralForm(number), - str = plurals[u][pluralForm(number)]; - if (f === 2) { - str = str[withoutSuffix ? 0 : 1]; - } - return str.replace(/%d/i, number); - }; - }, months = [ - 'كانون الثاني يناير', - 'شباط فبراير', - 'آذار مارس', - 'نيسان أبريل', - 'أيار مايو', - 'حزيران يونيو', - 'تموز يوليو', - 'آب أغسطس', - 'أيلول سبتمبر', - 'تشرين الأول أكتوبر', - 'تشرين الثاني نوفمبر', - 'كانون الأول ديسمبر' - ]; - - return moment.defineLocale('ar', { - months : months, - monthsShort : months, - weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), - weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), - weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return 'ص'; - } else { - return 'م'; - } - }, - calendar : { - sameDay: '[اليوم عند الساعة] LT', - nextDay: '[غدًا عند الساعة] LT', - nextWeek: 'dddd [عند الساعة] LT', - lastDay: '[أمس عند الساعة] LT', - lastWeek: 'dddd [عند الساعة] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'بعد %s', - past : 'منذ %s', - s : pluralize('s'), - m : pluralize('m'), - mm : pluralize('m'), - h : pluralize('h'), - hh : pluralize('h'), - d : pluralize('d'), - dd : pluralize('d'), - M : pluralize('M'), - MM : pluralize('M'), - y : pluralize('y'), - yy : pluralize('y') - }, - preparse: function (string) { - return string.replace(/[۰-۹]/g, function (match) { - return numberMap[match]; - }).replace(/،/g, ','); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }).replace(/,/g, '،'); - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : azerbaijani (az) -// author : topchiyev : https://github.com/topchiyev - -(function (factory) { - factory(moment); -}(function (moment) { - var suffixes = { - 1: '-inci', - 5: '-inci', - 8: '-inci', - 70: '-inci', - 80: '-inci', - - 2: '-nci', - 7: '-nci', - 20: '-nci', - 50: '-nci', - - 3: '-üncü', - 4: '-üncü', - 100: '-üncü', - - 6: '-ncı', - - 9: '-uncu', - 10: '-uncu', - 30: '-uncu', - - 60: '-ıncı', - 90: '-ıncı' - }; - return moment.defineLocale('az', { - months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), - monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), - weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), - weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), - weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[bugün saat] LT', - nextDay : '[sabah saat] LT', - nextWeek : '[gələn həftə] dddd [saat] LT', - lastDay : '[dünən] LT', - lastWeek : '[keçən həftə] dddd [saat] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s sonra', - past : '%s əvvəl', - s : 'birneçə saniyyə', - m : 'bir dəqiqə', - mm : '%d dəqiqə', - h : 'bir saat', - hh : '%d saat', - d : 'bir gün', - dd : '%d gün', - M : 'bir ay', - MM : '%d ay', - y : 'bir il', - yy : '%d il' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'gecə'; - } else if (hour < 12) { - return 'səhər'; - } else if (hour < 17) { - return 'gündüz'; - } else { - return 'axşam'; - } - }, - ordinal : function (number) { - if (number === 0) { // special case for zero - return number + '-ıncı'; - } - var a = number % 10, - b = number % 100 - a, - c = number >= 100 ? 100 : null; - - return number + (suffixes[a] || suffixes[b] || suffixes[c]); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : belarusian (be) -// author : Dmitry Demidov : https://github.com/demidov91 -// author: Praleska: http://praleska.pro/ -// Author : Menelion Elensúle : https://github.com/Oire - -(function (factory) { - factory(moment); -}(function (moment) { - function plural(word, num) { - var forms = word.split('_'); - return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); - } - - function relativeTimeWithPlural(number, withoutSuffix, key) { - var format = { - 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', - 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', - 'dd': 'дзень_дні_дзён', - 'MM': 'месяц_месяцы_месяцаў', - 'yy': 'год_гады_гадоў' - }; - if (key === 'm') { - return withoutSuffix ? 'хвіліна' : 'хвіліну'; - } - else if (key === 'h') { - return withoutSuffix ? 'гадзіна' : 'гадзіну'; - } - else { - return number + ' ' + plural(format[key], +number); - } - } - - function monthsCaseReplace(m, format) { - var months = { - 'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'), - 'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_') - }, - - nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return months[nounCase][m.month()]; - } - - function weekdaysCaseReplace(m, format) { - var weekdays = { - 'nominative': 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), - 'accusative': 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_') - }, - - nounCase = (/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/).test(format) ? - 'accusative' : - 'nominative'; - - return weekdays[nounCase][m.day()]; - } - - return moment.defineLocale('be', { - months : monthsCaseReplace, - monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), - weekdays : weekdaysCaseReplace, - weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), - weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY г.', - LLL : 'D MMMM YYYY г., LT', - LLLL : 'dddd, D MMMM YYYY г., LT' - }, - calendar : { - sameDay: '[Сёння ў] LT', - nextDay: '[Заўтра ў] LT', - lastDay: '[Учора ў] LT', - nextWeek: function () { - return '[У] dddd [ў] LT'; - }, - lastWeek: function () { - switch (this.day()) { - case 0: - case 3: - case 5: - case 6: - return '[У мінулую] dddd [ў] LT'; - case 1: - case 2: - case 4: - return '[У мінулы] dddd [ў] LT'; - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'праз %s', - past : '%s таму', - s : 'некалькі секунд', - m : relativeTimeWithPlural, - mm : relativeTimeWithPlural, - h : relativeTimeWithPlural, - hh : relativeTimeWithPlural, - d : 'дзень', - dd : relativeTimeWithPlural, - M : 'месяц', - MM : relativeTimeWithPlural, - y : 'год', - yy : relativeTimeWithPlural - }, - - - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'ночы'; - } else if (hour < 12) { - return 'раніцы'; - } else if (hour < 17) { - return 'дня'; - } else { - return 'вечара'; - } - }, - - ordinal: function (number, period) { - switch (period) { - case 'M': - case 'd': - case 'DDD': - case 'w': - case 'W': - return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы'; - case 'D': - return number + '-га'; - default: - return number; - } - }, - - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : bulgarian (bg) -// author : Krasen Borisov : https://github.com/kraz - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('bg', { - months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), - monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), - weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), - weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), - weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'D.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Днес в] LT', - nextDay : '[Утре в] LT', - nextWeek : 'dddd [в] LT', - lastDay : '[Вчера в] LT', - lastWeek : function () { - switch (this.day()) { - case 0: - case 3: - case 6: - return '[В изминалата] dddd [в] LT'; - case 1: - case 2: - case 4: - case 5: - return '[В изминалия] dddd [в] LT'; - } - }, - sameElse : 'L' - }, - relativeTime : { - future : 'след %s', - past : 'преди %s', - s : 'няколко секунди', - m : 'минута', - mm : '%d минути', - h : 'час', - hh : '%d часа', - d : 'ден', - dd : '%d дни', - M : 'месец', - MM : '%d месеца', - y : 'година', - yy : '%d години' - }, - ordinal : function (number) { - var lastDigit = number % 10, - last2Digits = number % 100; - if (number === 0) { - return number + '-ев'; - } else if (last2Digits === 0) { - return number + '-ен'; - } else if (last2Digits > 10 && last2Digits < 20) { - return number + '-ти'; - } else if (lastDigit === 1) { - return number + '-ви'; - } else if (lastDigit === 2) { - return number + '-ри'; - } else if (lastDigit === 7 || lastDigit === 8) { - return number + '-ми'; - } else { - return number + '-ти'; - } - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Bengali (bn) -// author : Kaushik Gandhi : https://github.com/kaushikgandhi - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '১', - '2': '২', - '3': '৩', - '4': '৪', - '5': '৫', - '6': '৬', - '7': '৭', - '8': '৮', - '9': '৯', - '0': '০' - }, - numberMap = { - '১': '1', - '২': '2', - '৩': '3', - '৪': '4', - '৫': '5', - '৬': '6', - '৭': '7', - '৮': '8', - '৯': '9', - '০': '0' - }; - - return moment.defineLocale('bn', { - months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), - monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), - weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'), - weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'), - weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), - longDateFormat : { - LT : 'A h:mm সময়', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[আজ] LT', - nextDay : '[আগামীকাল] LT', - nextWeek : 'dddd, LT', - lastDay : '[গতকাল] LT', - lastWeek : '[গত] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s পরে', - past : '%s আগে', - s : 'কএক সেকেন্ড', - m : 'এক মিনিট', - mm : '%d মিনিট', - h : 'এক ঘন্টা', - hh : '%d ঘন্টা', - d : 'এক দিন', - dd : '%d দিন', - M : 'এক মাস', - MM : '%d মাস', - y : 'এক বছর', - yy : '%d বছর' - }, - preparse: function (string) { - return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - //Bengali is a vast language its spoken - //in different forms in various parts of the world. - //I have just generalized with most common one used - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'রাত'; - } else if (hour < 10) { - return 'শকাল'; - } else if (hour < 17) { - return 'দুপুর'; - } else if (hour < 20) { - return 'বিকেল'; - } else { - return 'রাত'; - } - }, - week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : tibetan (bo) -// author : Thupten N. Chakrishar : https://github.com/vajradog - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '༡', - '2': '༢', - '3': '༣', - '4': '༤', - '5': '༥', - '6': '༦', - '7': '༧', - '8': '༨', - '9': '༩', - '0': '༠' - }, - numberMap = { - '༡': '1', - '༢': '2', - '༣': '3', - '༤': '4', - '༥': '5', - '༦': '6', - '༧': '7', - '༨': '8', - '༩': '9', - '༠': '0' - }; - - return moment.defineLocale('bo', { - months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), - monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), - weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), - weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), - weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), - longDateFormat : { - LT : 'A h:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[དི་རིང] LT', - nextDay : '[སང་ཉིན] LT', - nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT', - lastDay : '[ཁ་སང] LT', - lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s ལ་', - past : '%s སྔན་ལ', - s : 'ལམ་སང', - m : 'སྐར་མ་གཅིག', - mm : '%d སྐར་མ', - h : 'ཆུ་ཚོད་གཅིག', - hh : '%d ཆུ་ཚོད', - d : 'ཉིན་གཅིག', - dd : '%d ཉིན་', - M : 'ཟླ་བ་གཅིག', - MM : '%d ཟླ་བ', - y : 'ལོ་གཅིག', - yy : '%d ལོ' - }, - preparse: function (string) { - return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'མཚན་མོ'; - } else if (hour < 10) { - return 'ཞོགས་ཀས'; - } else if (hour < 17) { - return 'ཉིན་གུང'; - } else if (hour < 20) { - return 'དགོང་དག'; - } else { - return 'མཚན་མོ'; - } - }, - week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : breton (br) -// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou - -(function (factory) { - factory(moment); -}(function (moment) { - function relativeTimeWithMutation(number, withoutSuffix, key) { - var format = { - 'mm': 'munutenn', - 'MM': 'miz', - 'dd': 'devezh' - }; - return number + ' ' + mutation(format[key], number); - } - - function specialMutationForYears(number) { - switch (lastNumber(number)) { - case 1: - case 3: - case 4: - case 5: - case 9: - return number + ' bloaz'; - default: - return number + ' vloaz'; - } - } - - function lastNumber(number) { - if (number > 9) { - return lastNumber(number % 10); - } - return number; - } - - function mutation(text, number) { - if (number === 2) { - return softMutation(text); - } - return text; - } - - function softMutation(text) { - var mutationTable = { - 'm': 'v', - 'b': 'v', - 'd': 'z' - }; - if (mutationTable[text.charAt(0)] === undefined) { - return text; - } - return mutationTable[text.charAt(0)] + text.substring(1); - } - - return moment.defineLocale('br', { - months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'), - monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'), - weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'), - weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'), - weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'), - longDateFormat : { - LT : 'h[e]mm A', - L : 'DD/MM/YYYY', - LL : 'D [a viz] MMMM YYYY', - LLL : 'D [a viz] MMMM YYYY LT', - LLLL : 'dddd, D [a viz] MMMM YYYY LT' - }, - calendar : { - sameDay : '[Hiziv da] LT', - nextDay : '[Warc\'hoazh da] LT', - nextWeek : 'dddd [da] LT', - lastDay : '[Dec\'h da] LT', - lastWeek : 'dddd [paset da] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'a-benn %s', - past : '%s \'zo', - s : 'un nebeud segondennoù', - m : 'ur vunutenn', - mm : relativeTimeWithMutation, - h : 'un eur', - hh : '%d eur', - d : 'un devezh', - dd : relativeTimeWithMutation, - M : 'ur miz', - MM : relativeTimeWithMutation, - y : 'ur bloaz', - yy : specialMutationForYears - }, - ordinal : function (number) { - var output = (number === 1) ? 'añ' : 'vet'; - return number + output; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : bosnian (bs) -// author : Nedim Cholich : https://github.com/frontyard -// based on (hr) translation by Bojan Marković - -(function (factory) { - factory(moment); -}(function (moment) { - function translate(number, withoutSuffix, key) { - var result = number + ' '; - switch (key) { - case 'm': - return withoutSuffix ? 'jedna minuta' : 'jedne minute'; - case 'mm': - if (number === 1) { - result += 'minuta'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'minute'; - } else { - result += 'minuta'; - } - return result; - case 'h': - return withoutSuffix ? 'jedan sat' : 'jednog sata'; - case 'hh': - if (number === 1) { - result += 'sat'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'sata'; - } else { - result += 'sati'; - } - return result; - case 'dd': - if (number === 1) { - result += 'dan'; - } else { - result += 'dana'; - } - return result; - case 'MM': - if (number === 1) { - result += 'mjesec'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'mjeseca'; - } else { - result += 'mjeseci'; - } - return result; - case 'yy': - if (number === 1) { - result += 'godina'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'godine'; - } else { - result += 'godina'; - } - return result; - } - } - - return moment.defineLocale('bs', { - months : 'januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar'.split('_'), - monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), - weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), - weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), - weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD. MM. YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay : '[danas u] LT', - nextDay : '[sutra u] LT', - - nextWeek : function () { - switch (this.day()) { - case 0: - return '[u] [nedjelju] [u] LT'; - case 3: - return '[u] [srijedu] [u] LT'; - case 6: - return '[u] [subotu] [u] LT'; - case 1: - case 2: - case 4: - case 5: - return '[u] dddd [u] LT'; - } - }, - lastDay : '[jučer u] LT', - lastWeek : function () { - switch (this.day()) { - case 0: - case 3: - return '[prošlu] dddd [u] LT'; - case 6: - return '[prošle] [subote] [u] LT'; - case 1: - case 2: - case 4: - case 5: - return '[prošli] dddd [u] LT'; - } - }, - sameElse : 'L' - }, - relativeTime : { - future : 'za %s', - past : 'prije %s', - s : 'par sekundi', - m : translate, - mm : translate, - h : translate, - hh : translate, - d : 'dan', - dd : translate, - M : 'mjesec', - MM : translate, - y : 'godinu', - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : catalan (ca) -// author : Juan G. Hurtado : https://github.com/juanghurtado - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ca', { - months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), - monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), - weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), - weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), - weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay : function () { - return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; - }, - nextDay : function () { - return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; - }, - nextWeek : function () { - return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; - }, - lastDay : function () { - return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; - }, - lastWeek : function () { - return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; - }, - sameElse : 'L' - }, - relativeTime : { - future : 'en %s', - past : 'fa %s', - s : 'uns segons', - m : 'un minut', - mm : '%d minuts', - h : 'una hora', - hh : '%d hores', - d : 'un dia', - dd : '%d dies', - M : 'un mes', - MM : '%d mesos', - y : 'un any', - yy : '%d anys' - }, - ordinal : '%dº', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : czech (cs) -// author : petrbela : https://github.com/petrbela - -(function (factory) { - factory(moment); -}(function (moment) { - var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), - monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); - - function plural(n) { - return (n > 1) && (n < 5) && (~~(n / 10) !== 1); - } - - function translate(number, withoutSuffix, key, isFuture) { - var result = number + ' '; - switch (key) { - case 's': // a few seconds / in a few seconds / a few seconds ago - return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami'; - case 'm': // a minute / in a minute / a minute ago - return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); - case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'minuty' : 'minut'); - } else { - return result + 'minutami'; - } - break; - case 'h': // an hour / in an hour / an hour ago - return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); - case 'hh': // 9 hours / in 9 hours / 9 hours ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'hodiny' : 'hodin'); - } else { - return result + 'hodinami'; - } - break; - case 'd': // a day / in a day / a day ago - return (withoutSuffix || isFuture) ? 'den' : 'dnem'; - case 'dd': // 9 days / in 9 days / 9 days ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'dny' : 'dní'); - } else { - return result + 'dny'; - } - break; - case 'M': // a month / in a month / a month ago - return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; - case 'MM': // 9 months / in 9 months / 9 months ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'měsíce' : 'měsíců'); - } else { - return result + 'měsíci'; - } - break; - case 'y': // a year / in a year / a year ago - return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; - case 'yy': // 9 years / in 9 years / 9 years ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'roky' : 'let'); - } else { - return result + 'lety'; - } - break; - } - } - - return moment.defineLocale('cs', { - months : months, - monthsShort : monthsShort, - monthsParse : (function (months, monthsShort) { - var i, _monthsParse = []; - for (i = 0; i < 12; i++) { - // use custom parser to solve problem with July (červenec) - _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); - } - return _monthsParse; - }(months, monthsShort)), - weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'), - weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'), - weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'), - longDateFormat : { - LT: 'H:mm', - L : 'DD. MM. YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd D. MMMM YYYY LT' - }, - calendar : { - sameDay: '[dnes v] LT', - nextDay: '[zítra v] LT', - nextWeek: function () { - switch (this.day()) { - case 0: - return '[v neděli v] LT'; - case 1: - case 2: - return '[v] dddd [v] LT'; - case 3: - return '[ve středu v] LT'; - case 4: - return '[ve čtvrtek v] LT'; - case 5: - return '[v pátek v] LT'; - case 6: - return '[v sobotu v] LT'; - } - }, - lastDay: '[včera v] LT', - lastWeek: function () { - switch (this.day()) { - case 0: - return '[minulou neděli v] LT'; - case 1: - case 2: - return '[minulé] dddd [v] LT'; - case 3: - return '[minulou středu v] LT'; - case 4: - case 5: - return '[minulý] dddd [v] LT'; - case 6: - return '[minulou sobotu v] LT'; - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'za %s', - past : 'před %s', - s : translate, - m : translate, - mm : translate, - h : translate, - hh : translate, - d : translate, - dd : translate, - M : translate, - MM : translate, - y : translate, - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : chuvash (cv) -// author : Anatoly Mironov : https://github.com/mirontoli - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('cv', { - months : 'кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав'.split('_'), - monthsShort : 'кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш'.split('_'), - weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун'.split('_'), - weekdaysShort : 'выр_тун_ытл_юн_кĕç_эрн_шăм'.split('_'), - weekdaysMin : 'вр_тн_ыт_юн_кç_эр_шм'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD-MM-YYYY', - LL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]', - LLL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT', - LLLL : 'dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT' - }, - calendar : { - sameDay: '[Паян] LT [сехетре]', - nextDay: '[Ыран] LT [сехетре]', - lastDay: '[Ĕнер] LT [сехетре]', - nextWeek: '[Çитес] dddd LT [сехетре]', - lastWeek: '[Иртнĕ] dddd LT [сехетре]', - sameElse: 'L' - }, - relativeTime : { - future : function (output) { - var affix = /сехет$/i.exec(output) ? 'рен' : /çул$/i.exec(output) ? 'тан' : 'ран'; - return output + affix; - }, - past : '%s каялла', - s : 'пĕр-ик çеккунт', - m : 'пĕр минут', - mm : '%d минут', - h : 'пĕр сехет', - hh : '%d сехет', - d : 'пĕр кун', - dd : '%d кун', - M : 'пĕр уйăх', - MM : '%d уйăх', - y : 'пĕр çул', - yy : '%d çул' - }, - ordinal : '%d-мĕш', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Welsh (cy) -// author : Robert Allen - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('cy', { - months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), - monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), - weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), - weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), - weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), - // time formats are the same as en-gb - longDateFormat: { - LT: 'HH:mm', - L: 'DD/MM/YYYY', - LL: 'D MMMM YYYY', - LLL: 'D MMMM YYYY LT', - LLLL: 'dddd, D MMMM YYYY LT' - }, - calendar: { - sameDay: '[Heddiw am] LT', - nextDay: '[Yfory am] LT', - nextWeek: 'dddd [am] LT', - lastDay: '[Ddoe am] LT', - lastWeek: 'dddd [diwethaf am] LT', - sameElse: 'L' - }, - relativeTime: { - future: 'mewn %s', - past: '%s yn ôl', - s: 'ychydig eiliadau', - m: 'munud', - mm: '%d munud', - h: 'awr', - hh: '%d awr', - d: 'diwrnod', - dd: '%d diwrnod', - M: 'mis', - MM: '%d mis', - y: 'blwyddyn', - yy: '%d flynedd' - }, - // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh - ordinal: function (number) { - var b = number, - output = '', - lookup = [ - '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed - 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed - ]; - - if (b > 20) { - if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { - output = 'fed'; // not 30ain, 70ain or 90ain - } else { - output = 'ain'; - } - } else if (b > 0) { - output = lookup[b]; - } - - return number + output; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : danish (da) -// author : Ulrik Nielsen : https://github.com/mrbase - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('da', { - months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), - monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), - weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), - weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), - weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd [d.] D. MMMM YYYY LT' - }, - calendar : { - sameDay : '[I dag kl.] LT', - nextDay : '[I morgen kl.] LT', - nextWeek : 'dddd [kl.] LT', - lastDay : '[I går kl.] LT', - lastWeek : '[sidste] dddd [kl] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'om %s', - past : '%s siden', - s : 'få sekunder', - m : 'et minut', - mm : '%d minutter', - h : 'en time', - hh : '%d timer', - d : 'en dag', - dd : '%d dage', - M : 'en måned', - MM : '%d måneder', - y : 'et år', - yy : '%d år' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : austrian german (de-at) -// author : lluchs : https://github.com/lluchs -// author: Menelion Elensúle: https://github.com/Oire -// author : Martin Groller : https://github.com/MadMG - -(function (factory) { - factory(moment); -}(function (moment) { - function processRelativeTime(number, withoutSuffix, key, isFuture) { - var format = { - 'm': ['eine Minute', 'einer Minute'], - 'h': ['eine Stunde', 'einer Stunde'], - 'd': ['ein Tag', 'einem Tag'], - 'dd': [number + ' Tage', number + ' Tagen'], - 'M': ['ein Monat', 'einem Monat'], - 'MM': [number + ' Monate', number + ' Monaten'], - 'y': ['ein Jahr', 'einem Jahr'], - 'yy': [number + ' Jahre', number + ' Jahren'] - }; - return withoutSuffix ? format[key][0] : format[key][1]; - } - - return moment.defineLocale('de-at', { - months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), - monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), - weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), - weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), - weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), - longDateFormat : { - LT: 'HH:mm [Uhr]', - L : 'DD.MM.YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay: '[Heute um] LT', - sameElse: 'L', - nextDay: '[Morgen um] LT', - nextWeek: 'dddd [um] LT', - lastDay: '[Gestern um] LT', - lastWeek: '[letzten] dddd [um] LT' - }, - relativeTime : { - future : 'in %s', - past : 'vor %s', - s : 'ein paar Sekunden', - m : processRelativeTime, - mm : '%d Minuten', - h : processRelativeTime, - hh : '%d Stunden', - d : processRelativeTime, - dd : processRelativeTime, - M : processRelativeTime, - MM : processRelativeTime, - y : processRelativeTime, - yy : processRelativeTime - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : german (de) -// author : lluchs : https://github.com/lluchs -// author: Menelion Elensúle: https://github.com/Oire - -(function (factory) { - factory(moment); -}(function (moment) { - function processRelativeTime(number, withoutSuffix, key, isFuture) { - var format = { - 'm': ['eine Minute', 'einer Minute'], - 'h': ['eine Stunde', 'einer Stunde'], - 'd': ['ein Tag', 'einem Tag'], - 'dd': [number + ' Tage', number + ' Tagen'], - 'M': ['ein Monat', 'einem Monat'], - 'MM': [number + ' Monate', number + ' Monaten'], - 'y': ['ein Jahr', 'einem Jahr'], - 'yy': [number + ' Jahre', number + ' Jahren'] - }; - return withoutSuffix ? format[key][0] : format[key][1]; - } - - return moment.defineLocale('de', { - months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), - monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), - weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), - weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), - weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), - longDateFormat : { - LT: 'HH:mm [Uhr]', - L : 'DD.MM.YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay: '[Heute um] LT', - sameElse: 'L', - nextDay: '[Morgen um] LT', - nextWeek: 'dddd [um] LT', - lastDay: '[Gestern um] LT', - lastWeek: '[letzten] dddd [um] LT' - }, - relativeTime : { - future : 'in %s', - past : 'vor %s', - s : 'ein paar Sekunden', - m : processRelativeTime, - mm : '%d Minuten', - h : processRelativeTime, - hh : '%d Stunden', - d : processRelativeTime, - dd : processRelativeTime, - M : processRelativeTime, - MM : processRelativeTime, - y : processRelativeTime, - yy : processRelativeTime - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : modern greek (el) -// author : Aggelos Karalias : https://github.com/mehiel - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('el', { - monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'), - monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'), - months : function (momentToFormat, format) { - if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM' - return this._monthsGenitiveEl[momentToFormat.month()]; - } else { - return this._monthsNominativeEl[momentToFormat.month()]; - } - }, - monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'), - weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'), - weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'), - weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'), - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'μμ' : 'ΜΜ'; - } else { - return isLower ? 'πμ' : 'ΠΜ'; - } - }, - isPM : function (input) { - return ((input + '').toLowerCase()[0] === 'μ'); - }, - meridiemParse : /[ΠΜ]\.?Μ?\.?/i, - longDateFormat : { - LT : 'h:mm A', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendarEl : { - sameDay : '[Σήμερα {}] LT', - nextDay : '[Αύριο {}] LT', - nextWeek : 'dddd [{}] LT', - lastDay : '[Χθες {}] LT', - lastWeek : function () { - switch (this.day()) { - case 6: - return '[το προηγούμενο] dddd [{}] LT'; - default: - return '[την προηγούμενη] dddd [{}] LT'; - } - }, - sameElse : 'L' - }, - calendar : function (key, mom) { - var output = this._calendarEl[key], - hours = mom && mom.hours(); - - if (typeof output === 'function') { - output = output.apply(mom); - } - - return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις')); - }, - relativeTime : { - future : 'σε %s', - past : '%s πριν', - s : 'δευτερόλεπτα', - m : 'ένα λεπτό', - mm : '%d λεπτά', - h : 'μία ώρα', - hh : '%d ώρες', - d : 'μία μέρα', - dd : '%d μέρες', - M : 'ένας μήνας', - MM : '%d μήνες', - y : 'ένας χρόνος', - yy : '%d χρόνια' - }, - ordinal : function (number) { - return number + 'η'; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : australian english (en-au) - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('en-au', { - months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - longDateFormat : { - LT : 'h:mm A', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'in %s', - past : '%s ago', - s : 'a few seconds', - m : 'a minute', - mm : '%d minutes', - h : 'an hour', - hh : '%d hours', - d : 'a day', - dd : '%d days', - M : 'a month', - MM : '%d months', - y : 'a year', - yy : '%d years' - }, - ordinal : function (number) { - var b = number % 10, - output = (~~(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : canadian english (en-ca) -// author : Jonathan Abourbih : https://github.com/jonbca - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('en-ca', { - months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - longDateFormat : { - LT : 'h:mm A', - L : 'YYYY-MM-DD', - LL : 'D MMMM, YYYY', - LLL : 'D MMMM, YYYY LT', - LLLL : 'dddd, D MMMM, YYYY LT' - }, - calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'in %s', - past : '%s ago', - s : 'a few seconds', - m : 'a minute', - mm : '%d minutes', - h : 'an hour', - hh : '%d hours', - d : 'a day', - dd : '%d days', - M : 'a month', - MM : '%d months', - y : 'a year', - yy : '%d years' - }, - ordinal : function (number) { - var b = number % 10, - output = (~~(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - } - }); -})); -// moment.js locale configuration -// locale : great britain english (en-gb) -// author : Chris Gedrim : https://github.com/chrisgedrim - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('en-gb', { - months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'in %s', - past : '%s ago', - s : 'a few seconds', - m : 'a minute', - mm : '%d minutes', - h : 'an hour', - hh : '%d hours', - d : 'a day', - dd : '%d days', - M : 'a month', - MM : '%d months', - y : 'a year', - yy : '%d years' - }, - ordinal : function (number) { - var b = number % 10, - output = (~~(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - return number + output; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : esperanto (eo) -// author : Colin Dean : https://github.com/colindean -// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. -// Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('eo', { - months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), - monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), - weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), - weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), - weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'YYYY-MM-DD', - LL : 'D[-an de] MMMM, YYYY', - LLL : 'D[-an de] MMMM, YYYY LT', - LLLL : 'dddd, [la] D[-an de] MMMM, YYYY LT' - }, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'p.t.m.' : 'P.T.M.'; - } else { - return isLower ? 'a.t.m.' : 'A.T.M.'; - } - }, - calendar : { - sameDay : '[Hodiaŭ je] LT', - nextDay : '[Morgaŭ je] LT', - nextWeek : 'dddd [je] LT', - lastDay : '[Hieraŭ je] LT', - lastWeek : '[pasinta] dddd [je] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'je %s', - past : 'antaŭ %s', - s : 'sekundoj', - m : 'minuto', - mm : '%d minutoj', - h : 'horo', - hh : '%d horoj', - d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo - dd : '%d tagoj', - M : 'monato', - MM : '%d monatoj', - y : 'jaro', - yy : '%d jaroj' - }, - ordinal : '%da', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : spanish (es) -// author : Julio Napurí : https://github.com/julionc - -(function (factory) { - factory(moment); -}(function (moment) { - var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), - monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); - - return moment.defineLocale('es', { - months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), - monthsShort : function (m, format) { - if (/-MMM-/.test(format)) { - return monthsShort[m.month()]; - } else { - return monthsShortDot[m.month()]; - } - }, - weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), - weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), - weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD/MM/YYYY', - LL : 'D [de] MMMM [de] YYYY', - LLL : 'D [de] MMMM [de] YYYY LT', - LLLL : 'dddd, D [de] MMMM [de] YYYY LT' - }, - calendar : { - sameDay : function () { - return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; - }, - nextDay : function () { - return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; - }, - nextWeek : function () { - return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; - }, - lastDay : function () { - return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; - }, - lastWeek : function () { - return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; - }, - sameElse : 'L' - }, - relativeTime : { - future : 'en %s', - past : 'hace %s', - s : 'unos segundos', - m : 'un minuto', - mm : '%d minutos', - h : 'una hora', - hh : '%d horas', - d : 'un día', - dd : '%d días', - M : 'un mes', - MM : '%d meses', - y : 'un año', - yy : '%d años' - }, - ordinal : '%dº', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : estonian (et) -// author : Henry Kehlmann : https://github.com/madhenry -// improvements : Illimar Tambek : https://github.com/ragulka - -(function (factory) { - factory(moment); -}(function (moment) { - function processRelativeTime(number, withoutSuffix, key, isFuture) { - var format = { - 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], - 'm' : ['ühe minuti', 'üks minut'], - 'mm': [number + ' minuti', number + ' minutit'], - 'h' : ['ühe tunni', 'tund aega', 'üks tund'], - 'hh': [number + ' tunni', number + ' tundi'], - 'd' : ['ühe päeva', 'üks päev'], - 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], - 'MM': [number + ' kuu', number + ' kuud'], - 'y' : ['ühe aasta', 'aasta', 'üks aasta'], - 'yy': [number + ' aasta', number + ' aastat'] - }; - if (withoutSuffix) { - return format[key][2] ? format[key][2] : format[key][1]; - } - return isFuture ? format[key][0] : format[key][1]; - } - - return moment.defineLocale('et', { - months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'), - monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'), - weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'), - weekdaysShort : 'P_E_T_K_N_R_L'.split('_'), - weekdaysMin : 'P_E_T_K_N_R_L'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD.MM.YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay : '[Täna,] LT', - nextDay : '[Homme,] LT', - nextWeek : '[Järgmine] dddd LT', - lastDay : '[Eile,] LT', - lastWeek : '[Eelmine] dddd LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s pärast', - past : '%s tagasi', - s : processRelativeTime, - m : processRelativeTime, - mm : processRelativeTime, - h : processRelativeTime, - hh : processRelativeTime, - d : processRelativeTime, - dd : '%d päeva', - M : processRelativeTime, - MM : processRelativeTime, - y : processRelativeTime, - yy : processRelativeTime - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : euskara (eu) -// author : Eneko Illarramendi : https://github.com/eillarra - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('eu', { - months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), - monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), - weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), - weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), - weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'YYYY-MM-DD', - LL : 'YYYY[ko] MMMM[ren] D[a]', - LLL : 'YYYY[ko] MMMM[ren] D[a] LT', - LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] LT', - l : 'YYYY-M-D', - ll : 'YYYY[ko] MMM D[a]', - lll : 'YYYY[ko] MMM D[a] LT', - llll : 'ddd, YYYY[ko] MMM D[a] LT' - }, - calendar : { - sameDay : '[gaur] LT[etan]', - nextDay : '[bihar] LT[etan]', - nextWeek : 'dddd LT[etan]', - lastDay : '[atzo] LT[etan]', - lastWeek : '[aurreko] dddd LT[etan]', - sameElse : 'L' - }, - relativeTime : { - future : '%s barru', - past : 'duela %s', - s : 'segundo batzuk', - m : 'minutu bat', - mm : '%d minutu', - h : 'ordu bat', - hh : '%d ordu', - d : 'egun bat', - dd : '%d egun', - M : 'hilabete bat', - MM : '%d hilabete', - y : 'urte bat', - yy : '%d urte' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Persian (fa) -// author : Ebrahim Byagowi : https://github.com/ebraminio - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '۱', - '2': '۲', - '3': '۳', - '4': '۴', - '5': '۵', - '6': '۶', - '7': '۷', - '8': '۸', - '9': '۹', - '0': '۰' - }, numberMap = { - '۱': '1', - '۲': '2', - '۳': '3', - '۴': '4', - '۵': '5', - '۶': '6', - '۷': '7', - '۸': '8', - '۹': '9', - '۰': '0' - }; - - return moment.defineLocale('fa', { - months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), - monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), - weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), - weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), - weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return 'قبل از ظهر'; - } else { - return 'بعد از ظهر'; - } - }, - calendar : { - sameDay : '[امروز ساعت] LT', - nextDay : '[فردا ساعت] LT', - nextWeek : 'dddd [ساعت] LT', - lastDay : '[دیروز ساعت] LT', - lastWeek : 'dddd [پیش] [ساعت] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'در %s', - past : '%s پیش', - s : 'چندین ثانیه', - m : 'یک دقیقه', - mm : '%d دقیقه', - h : 'یک ساعت', - hh : '%d ساعت', - d : 'یک روز', - dd : '%d روز', - M : 'یک ماه', - MM : '%d ماه', - y : 'یک سال', - yy : '%d سال' - }, - preparse: function (string) { - return string.replace(/[۰-۹]/g, function (match) { - return numberMap[match]; - }).replace(/،/g, ','); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }).replace(/,/g, '،'); - }, - ordinal : '%dم', - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : finnish (fi) -// author : Tarmo Aidantausta : https://github.com/bleadof - -(function (factory) { - factory(moment); -}(function (moment) { - var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), - numbersFuture = [ - 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', - numbersPast[7], numbersPast[8], numbersPast[9] - ]; - - function translate(number, withoutSuffix, key, isFuture) { - var result = ''; - switch (key) { - case 's': - return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; - case 'm': - return isFuture ? 'minuutin' : 'minuutti'; - case 'mm': - result = isFuture ? 'minuutin' : 'minuuttia'; - break; - case 'h': - return isFuture ? 'tunnin' : 'tunti'; - case 'hh': - result = isFuture ? 'tunnin' : 'tuntia'; - break; - case 'd': - return isFuture ? 'päivän' : 'päivä'; - case 'dd': - result = isFuture ? 'päivän' : 'päivää'; - break; - case 'M': - return isFuture ? 'kuukauden' : 'kuukausi'; - case 'MM': - result = isFuture ? 'kuukauden' : 'kuukautta'; - break; - case 'y': - return isFuture ? 'vuoden' : 'vuosi'; - case 'yy': - result = isFuture ? 'vuoden' : 'vuotta'; - break; - } - result = verbalNumber(number, isFuture) + ' ' + result; - return result; - } - - function verbalNumber(number, isFuture) { - return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; - } - - return moment.defineLocale('fi', { - months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), - monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'), - weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'), - weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'), - weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'), - longDateFormat : { - LT : 'HH.mm', - L : 'DD.MM.YYYY', - LL : 'Do MMMM[ta] YYYY', - LLL : 'Do MMMM[ta] YYYY, [klo] LT', - LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] LT', - l : 'D.M.YYYY', - ll : 'Do MMM YYYY', - lll : 'Do MMM YYYY, [klo] LT', - llll : 'ddd, Do MMM YYYY, [klo] LT' - }, - calendar : { - sameDay : '[tänään] [klo] LT', - nextDay : '[huomenna] [klo] LT', - nextWeek : 'dddd [klo] LT', - lastDay : '[eilen] [klo] LT', - lastWeek : '[viime] dddd[na] [klo] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s päästä', - past : '%s sitten', - s : translate, - m : translate, - mm : translate, - h : translate, - hh : translate, - d : translate, - dd : translate, - M : translate, - MM : translate, - y : translate, - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : faroese (fo) -// author : Ragnar Johannesen : https://github.com/ragnar123 - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('fo', { - months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), - monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), - weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), - weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), - weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D. MMMM, YYYY LT' - }, - calendar : { - sameDay : '[Í dag kl.] LT', - nextDay : '[Í morgin kl.] LT', - nextWeek : 'dddd [kl.] LT', - lastDay : '[Í gjár kl.] LT', - lastWeek : '[síðstu] dddd [kl] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'um %s', - past : '%s síðani', - s : 'fá sekund', - m : 'ein minutt', - mm : '%d minuttir', - h : 'ein tími', - hh : '%d tímar', - d : 'ein dagur', - dd : '%d dagar', - M : 'ein mánaði', - MM : '%d mánaðir', - y : 'eitt ár', - yy : '%d ár' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : canadian french (fr-ca) -// author : Jonathan Abourbih : https://github.com/jonbca - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('fr-ca', { - months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), - monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), - weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), - weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), - weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'YYYY-MM-DD', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[Aujourd\'hui à] LT', - nextDay: '[Demain à] LT', - nextWeek: 'dddd [à] LT', - lastDay: '[Hier à] LT', - lastWeek: 'dddd [dernier à] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'dans %s', - past : 'il y a %s', - s : 'quelques secondes', - m : 'une minute', - mm : '%d minutes', - h : 'une heure', - hh : '%d heures', - d : 'un jour', - dd : '%d jours', - M : 'un mois', - MM : '%d mois', - y : 'un an', - yy : '%d ans' - }, - ordinal : function (number) { - return number + (number === 1 ? 'er' : ''); - } - }); -})); -// moment.js locale configuration -// locale : french (fr) -// author : John Fischer : https://github.com/jfroffice - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('fr', { - months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), - monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), - weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), - weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), - weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[Aujourd\'hui à] LT', - nextDay: '[Demain à] LT', - nextWeek: 'dddd [à] LT', - lastDay: '[Hier à] LT', - lastWeek: 'dddd [dernier à] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'dans %s', - past : 'il y a %s', - s : 'quelques secondes', - m : 'une minute', - mm : '%d minutes', - h : 'une heure', - hh : '%d heures', - d : 'un jour', - dd : '%d jours', - M : 'un mois', - MM : '%d mois', - y : 'un an', - yy : '%d ans' - }, - ordinal : function (number) { - return number + (number === 1 ? 'er' : ''); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : galician (gl) -// author : Juan G. Hurtado : https://github.com/juanghurtado - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('gl', { - months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), - monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), - weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), - weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), - weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay : function () { - return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; - }, - nextDay : function () { - return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; - }, - nextWeek : function () { - return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; - }, - lastDay : function () { - return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; - }, - lastWeek : function () { - return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; - }, - sameElse : 'L' - }, - relativeTime : { - future : function (str) { - if (str === 'uns segundos') { - return 'nuns segundos'; - } - return 'en ' + str; - }, - past : 'hai %s', - s : 'uns segundos', - m : 'un minuto', - mm : '%d minutos', - h : 'unha hora', - hh : '%d horas', - d : 'un día', - dd : '%d días', - M : 'un mes', - MM : '%d meses', - y : 'un ano', - yy : '%d anos' - }, - ordinal : '%dº', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Hebrew (he) -// author : Tomer Cohen : https://github.com/tomer -// author : Moshe Simantov : https://github.com/DevelopmentIL -// author : Tal Ater : https://github.com/TalAter - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('he', { - months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), - monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), - weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), - weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), - weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D [ב]MMMM YYYY', - LLL : 'D [ב]MMMM YYYY LT', - LLLL : 'dddd, D [ב]MMMM YYYY LT', - l : 'D/M/YYYY', - ll : 'D MMM YYYY', - lll : 'D MMM YYYY LT', - llll : 'ddd, D MMM YYYY LT' - }, - calendar : { - sameDay : '[היום ב־]LT', - nextDay : '[מחר ב־]LT', - nextWeek : 'dddd [בשעה] LT', - lastDay : '[אתמול ב־]LT', - lastWeek : '[ביום] dddd [האחרון בשעה] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'בעוד %s', - past : 'לפני %s', - s : 'מספר שניות', - m : 'דקה', - mm : '%d דקות', - h : 'שעה', - hh : function (number) { - if (number === 2) { - return 'שעתיים'; - } - return number + ' שעות'; - }, - d : 'יום', - dd : function (number) { - if (number === 2) { - return 'יומיים'; - } - return number + ' ימים'; - }, - M : 'חודש', - MM : function (number) { - if (number === 2) { - return 'חודשיים'; - } - return number + ' חודשים'; - }, - y : 'שנה', - yy : function (number) { - if (number === 2) { - return 'שנתיים'; - } - return number + ' שנים'; - } - } - }); -})); -// moment.js locale configuration -// locale : hindi (hi) -// author : Mayank Singhal : https://github.com/mayanksinghal - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '१', - '2': '२', - '3': '३', - '4': '४', - '5': '५', - '6': '६', - '7': '७', - '8': '८', - '9': '९', - '0': '०' - }, - numberMap = { - '१': '1', - '२': '2', - '३': '3', - '४': '4', - '५': '5', - '६': '6', - '७': '7', - '८': '8', - '९': '9', - '०': '0' - }; - - return moment.defineLocale('hi', { - months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), - monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), - weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), - weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), - weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), - longDateFormat : { - LT : 'A h:mm बजे', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[आज] LT', - nextDay : '[कल] LT', - nextWeek : 'dddd, LT', - lastDay : '[कल] LT', - lastWeek : '[पिछले] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s में', - past : '%s पहले', - s : 'कुछ ही क्षण', - m : 'एक मिनट', - mm : '%d मिनट', - h : 'एक घंटा', - hh : '%d घंटे', - d : 'एक दिन', - dd : '%d दिन', - M : 'एक महीने', - MM : '%d महीने', - y : 'एक वर्ष', - yy : '%d वर्ष' - }, - preparse: function (string) { - return string.replace(/[१२३४५६७८९०]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - // Hindi notation for meridiems are quite fuzzy in practice. While there exists - // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'रात'; - } else if (hour < 10) { - return 'सुबह'; - } else if (hour < 17) { - return 'दोपहर'; - } else if (hour < 20) { - return 'शाम'; - } else { - return 'रात'; - } - }, - week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : hrvatski (hr) -// author : Bojan Marković : https://github.com/bmarkovic - -// based on (sl) translation by Robert Sedovšek - -(function (factory) { - factory(moment); -}(function (moment) { - function translate(number, withoutSuffix, key) { - var result = number + ' '; - switch (key) { - case 'm': - return withoutSuffix ? 'jedna minuta' : 'jedne minute'; - case 'mm': - if (number === 1) { - result += 'minuta'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'minute'; - } else { - result += 'minuta'; - } - return result; - case 'h': - return withoutSuffix ? 'jedan sat' : 'jednog sata'; - case 'hh': - if (number === 1) { - result += 'sat'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'sata'; - } else { - result += 'sati'; - } - return result; - case 'dd': - if (number === 1) { - result += 'dan'; - } else { - result += 'dana'; - } - return result; - case 'MM': - if (number === 1) { - result += 'mjesec'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'mjeseca'; - } else { - result += 'mjeseci'; - } - return result; - case 'yy': - if (number === 1) { - result += 'godina'; - } else if (number === 2 || number === 3 || number === 4) { - result += 'godine'; - } else { - result += 'godina'; - } - return result; - } - } - - return moment.defineLocale('hr', { - months : 'sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'), - monthsShort : 'sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), - weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), - weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), - weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD. MM. YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay : '[danas u] LT', - nextDay : '[sutra u] LT', - - nextWeek : function () { - switch (this.day()) { - case 0: - return '[u] [nedjelju] [u] LT'; - case 3: - return '[u] [srijedu] [u] LT'; - case 6: - return '[u] [subotu] [u] LT'; - case 1: - case 2: - case 4: - case 5: - return '[u] dddd [u] LT'; - } - }, - lastDay : '[jučer u] LT', - lastWeek : function () { - switch (this.day()) { - case 0: - case 3: - return '[prošlu] dddd [u] LT'; - case 6: - return '[prošle] [subote] [u] LT'; - case 1: - case 2: - case 4: - case 5: - return '[prošli] dddd [u] LT'; - } - }, - sameElse : 'L' - }, - relativeTime : { - future : 'za %s', - past : 'prije %s', - s : 'par sekundi', - m : translate, - mm : translate, - h : translate, - hh : translate, - d : 'dan', - dd : translate, - M : 'mjesec', - MM : translate, - y : 'godinu', - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : hungarian (hu) -// author : Adam Brunner : https://github.com/adambrunner - -(function (factory) { - factory(moment); -}(function (moment) { - var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); - - function translate(number, withoutSuffix, key, isFuture) { - var num = number, - suffix; - - switch (key) { - case 's': - return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; - case 'm': - return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); - case 'mm': - return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); - case 'h': - return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); - case 'hh': - return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); - case 'd': - return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); - case 'dd': - return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); - case 'M': - return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); - case 'MM': - return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); - case 'y': - return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); - case 'yy': - return num + (isFuture || withoutSuffix ? ' év' : ' éve'); - } - - return ''; - } - - function week(isFuture) { - return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; - } - - return moment.defineLocale('hu', { - months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'), - monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'), - weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'), - weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), - weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'YYYY.MM.DD.', - LL : 'YYYY. MMMM D.', - LLL : 'YYYY. MMMM D., LT', - LLLL : 'YYYY. MMMM D., dddd LT' - }, - meridiem : function (hours, minutes, isLower) { - if (hours < 12) { - return isLower === true ? 'de' : 'DE'; - } else { - return isLower === true ? 'du' : 'DU'; - } - }, - calendar : { - sameDay : '[ma] LT[-kor]', - nextDay : '[holnap] LT[-kor]', - nextWeek : function () { - return week.call(this, true); - }, - lastDay : '[tegnap] LT[-kor]', - lastWeek : function () { - return week.call(this, false); - }, - sameElse : 'L' - }, - relativeTime : { - future : '%s múlva', - past : '%s', - s : translate, - m : translate, - mm : translate, - h : translate, - hh : translate, - d : translate, - dd : translate, - M : translate, - MM : translate, - y : translate, - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Armenian (hy-am) -// author : Armendarabyan : https://github.com/armendarabyan - -(function (factory) { - factory(moment); -}(function (moment) { - function monthsCaseReplace(m, format) { - var months = { - 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), - 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') - }, - - nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return months[nounCase][m.month()]; - } - - function monthsShortCaseReplace(m, format) { - var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'); - - return monthsShort[m.month()]; - } - - function weekdaysCaseReplace(m, format) { - var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'); - - return weekdays[m.day()]; - } - - return moment.defineLocale('hy-am', { - months : monthsCaseReplace, - monthsShort : monthsShortCaseReplace, - weekdays : weekdaysCaseReplace, - weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), - weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY թ.', - LLL : 'D MMMM YYYY թ., LT', - LLLL : 'dddd, D MMMM YYYY թ., LT' - }, - calendar : { - sameDay: '[այսօր] LT', - nextDay: '[վաղը] LT', - lastDay: '[երեկ] LT', - nextWeek: function () { - return 'dddd [օրը ժամը] LT'; - }, - lastWeek: function () { - return '[անցած] dddd [օրը ժամը] LT'; - }, - sameElse: 'L' - }, - relativeTime : { - future : '%s հետո', - past : '%s առաջ', - s : 'մի քանի վայրկյան', - m : 'րոպե', - mm : '%d րոպե', - h : 'ժամ', - hh : '%d ժամ', - d : 'օր', - dd : '%d օր', - M : 'ամիս', - MM : '%d ամիս', - y : 'տարի', - yy : '%d տարի' - }, - - meridiem : function (hour) { - if (hour < 4) { - return 'գիշերվա'; - } else if (hour < 12) { - return 'առավոտվա'; - } else if (hour < 17) { - return 'ցերեկվա'; - } else { - return 'երեկոյան'; - } - }, - - ordinal: function (number, period) { - switch (period) { - case 'DDD': - case 'w': - case 'W': - case 'DDDo': - if (number === 1) { - return number + '-ին'; - } - return number + '-րդ'; - default: - return number; - } - }, - - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Bahasa Indonesia (id) -// author : Mohammad Satrio Utomo : https://github.com/tyok -// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('id', { - months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'), - monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'), - weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'), - weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'), - weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'), - longDateFormat : { - LT : 'HH.mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY [pukul] LT', - LLLL : 'dddd, D MMMM YYYY [pukul] LT' - }, - meridiem : function (hours, minutes, isLower) { - if (hours < 11) { - return 'pagi'; - } else if (hours < 15) { - return 'siang'; - } else if (hours < 19) { - return 'sore'; - } else { - return 'malam'; - } - }, - calendar : { - sameDay : '[Hari ini pukul] LT', - nextDay : '[Besok pukul] LT', - nextWeek : 'dddd [pukul] LT', - lastDay : '[Kemarin pukul] LT', - lastWeek : 'dddd [lalu pukul] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'dalam %s', - past : '%s yang lalu', - s : 'beberapa detik', - m : 'semenit', - mm : '%d menit', - h : 'sejam', - hh : '%d jam', - d : 'sehari', - dd : '%d hari', - M : 'sebulan', - MM : '%d bulan', - y : 'setahun', - yy : '%d tahun' - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : icelandic (is) -// author : Hinrik Örn Sigurðsson : https://github.com/hinrik - -(function (factory) { - factory(moment); -}(function (moment) { - function plural(n) { - if (n % 100 === 11) { - return true; - } else if (n % 10 === 1) { - return false; - } - return true; - } - - function translate(number, withoutSuffix, key, isFuture) { - var result = number + ' '; - switch (key) { - case 's': - return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; - case 'm': - return withoutSuffix ? 'mínúta' : 'mínútu'; - case 'mm': - if (plural(number)) { - return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); - } else if (withoutSuffix) { - return result + 'mínúta'; - } - return result + 'mínútu'; - case 'hh': - if (plural(number)) { - return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); - } - return result + 'klukkustund'; - case 'd': - if (withoutSuffix) { - return 'dagur'; - } - return isFuture ? 'dag' : 'degi'; - case 'dd': - if (plural(number)) { - if (withoutSuffix) { - return result + 'dagar'; - } - return result + (isFuture ? 'daga' : 'dögum'); - } else if (withoutSuffix) { - return result + 'dagur'; - } - return result + (isFuture ? 'dag' : 'degi'); - case 'M': - if (withoutSuffix) { - return 'mánuður'; - } - return isFuture ? 'mánuð' : 'mánuði'; - case 'MM': - if (plural(number)) { - if (withoutSuffix) { - return result + 'mánuðir'; - } - return result + (isFuture ? 'mánuði' : 'mánuðum'); - } else if (withoutSuffix) { - return result + 'mánuður'; - } - return result + (isFuture ? 'mánuð' : 'mánuði'); - case 'y': - return withoutSuffix || isFuture ? 'ár' : 'ári'; - case 'yy': - if (plural(number)) { - return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); - } - return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); - } - } - - return moment.defineLocale('is', { - months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'), - monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'), - weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'), - weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'), - weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD/MM/YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY [kl.] LT', - LLLL : 'dddd, D. MMMM YYYY [kl.] LT' - }, - calendar : { - sameDay : '[í dag kl.] LT', - nextDay : '[á morgun kl.] LT', - nextWeek : 'dddd [kl.] LT', - lastDay : '[í gær kl.] LT', - lastWeek : '[síðasta] dddd [kl.] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'eftir %s', - past : 'fyrir %s síðan', - s : translate, - m : translate, - mm : translate, - h : 'klukkustund', - hh : translate, - d : translate, - dd : translate, - M : translate, - MM : translate, - y : translate, - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : italian (it) -// author : Lorenzo : https://github.com/aliem -// author: Mattia Larentis: https://github.com/nostalgiaz - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('it', { - months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), - monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), - weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), - weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), - weekdaysMin : 'D_L_Ma_Me_G_V_S'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay: '[Oggi alle] LT', - nextDay: '[Domani alle] LT', - nextWeek: 'dddd [alle] LT', - lastDay: '[Ieri alle] LT', - lastWeek: '[lo scorso] dddd [alle] LT', - sameElse: 'L' - }, - relativeTime : { - future : function (s) { - return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; - }, - past : '%s fa', - s : 'alcuni secondi', - m : 'un minuto', - mm : '%d minuti', - h : 'un\'ora', - hh : '%d ore', - d : 'un giorno', - dd : '%d giorni', - M : 'un mese', - MM : '%d mesi', - y : 'un anno', - yy : '%d anni' - }, - ordinal: '%dº', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : japanese (ja) -// author : LI Long : https://github.com/baryon - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ja', { - months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), - monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), - weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), - weekdaysShort : '日_月_火_水_木_金_土'.split('_'), - weekdaysMin : '日_月_火_水_木_金_土'.split('_'), - longDateFormat : { - LT : 'Ah時m分', - L : 'YYYY/MM/DD', - LL : 'YYYY年M月D日', - LLL : 'YYYY年M月D日LT', - LLLL : 'YYYY年M月D日LT dddd' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return '午前'; - } else { - return '午後'; - } - }, - calendar : { - sameDay : '[今日] LT', - nextDay : '[明日] LT', - nextWeek : '[来週]dddd LT', - lastDay : '[昨日] LT', - lastWeek : '[前週]dddd LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s後', - past : '%s前', - s : '数秒', - m : '1分', - mm : '%d分', - h : '1時間', - hh : '%d時間', - d : '1日', - dd : '%d日', - M : '1ヶ月', - MM : '%dヶ月', - y : '1年', - yy : '%d年' - } - }); -})); -// moment.js locale configuration -// locale : Georgian (ka) -// author : Irakli Janiashvili : https://github.com/irakli-janiashvili - -(function (factory) { - factory(moment); -}(function (moment) { - function monthsCaseReplace(m, format) { - var months = { - 'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), - 'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') - }, - - nounCase = (/D[oD] *MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return months[nounCase][m.month()]; - } - - function weekdaysCaseReplace(m, format) { - var weekdays = { - 'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), - 'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_') - }, - - nounCase = (/(წინა|შემდეგ)/).test(format) ? - 'accusative' : - 'nominative'; - - return weekdays[nounCase][m.day()]; - } - - return moment.defineLocale('ka', { - months : monthsCaseReplace, - monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), - weekdays : weekdaysCaseReplace, - weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), - weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), - longDateFormat : { - LT : 'h:mm A', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[დღეს] LT[-ზე]', - nextDay : '[ხვალ] LT[-ზე]', - lastDay : '[გუშინ] LT[-ზე]', - nextWeek : '[შემდეგ] dddd LT[-ზე]', - lastWeek : '[წინა] dddd LT-ზე', - sameElse : 'L' - }, - relativeTime : { - future : function (s) { - return (/(წამი|წუთი|საათი|წელი)/).test(s) ? - s.replace(/ი$/, 'ში') : - s + 'ში'; - }, - past : function (s) { - if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { - return s.replace(/(ი|ე)$/, 'ის წინ'); - } - if ((/წელი/).test(s)) { - return s.replace(/წელი$/, 'წლის წინ'); - } - }, - s : 'რამდენიმე წამი', - m : 'წუთი', - mm : '%d წუთი', - h : 'საათი', - hh : '%d საათი', - d : 'დღე', - dd : '%d დღე', - M : 'თვე', - MM : '%d თვე', - y : 'წელი', - yy : '%d წელი' - }, - ordinal : function (number) { - if (number === 0) { - return number; - } - - if (number === 1) { - return number + '-ლი'; - } - - if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { - return 'მე-' + number; - } - - return number + '-ე'; - }, - week : { - dow : 1, - doy : 7 - } - }); -})); -// moment.js locale configuration -// locale : khmer (km) -// author : Kruy Vanna : https://github.com/kruyvanna - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('km', { - months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), - monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), - weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), - weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), - weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), - longDateFormat: { - LT: 'HH:mm', - L: 'DD/MM/YYYY', - LL: 'D MMMM YYYY', - LLL: 'D MMMM YYYY LT', - LLLL: 'dddd, D MMMM YYYY LT' - }, - calendar: { - sameDay: '[ថ្ងៃនៈ ម៉ោង] LT', - nextDay: '[ស្អែក ម៉ោង] LT', - nextWeek: 'dddd [ម៉ោង] LT', - lastDay: '[ម្សិលមិញ ម៉ោង] LT', - lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', - sameElse: 'L' - }, - relativeTime: { - future: '%sទៀត', - past: '%sមុន', - s: 'ប៉ុន្មានវិនាទី', - m: 'មួយនាទី', - mm: '%d នាទី', - h: 'មួយម៉ោង', - hh: '%d ម៉ោង', - d: 'មួយថ្ងៃ', - dd: '%d ថ្ងៃ', - M: 'មួយខែ', - MM: '%d ខែ', - y: 'មួយឆ្នាំ', - yy: '%d ឆ្នាំ' - }, - week: { - dow: 1, // Monday is the first day of the week. - doy: 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : korean (ko) -// -// authors -// -// - Kyungwook, Park : https://github.com/kyungw00k -// - Jeeeyul Lee -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ko', { - months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), - monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), - weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), - weekdaysShort : '일_월_화_수_목_금_토'.split('_'), - weekdaysMin : '일_월_화_수_목_금_토'.split('_'), - longDateFormat : { - LT : 'A h시 m분', - L : 'YYYY.MM.DD', - LL : 'YYYY년 MMMM D일', - LLL : 'YYYY년 MMMM D일 LT', - LLLL : 'YYYY년 MMMM D일 dddd LT' - }, - meridiem : function (hour, minute, isUpper) { - return hour < 12 ? '오전' : '오후'; - }, - calendar : { - sameDay : '오늘 LT', - nextDay : '내일 LT', - nextWeek : 'dddd LT', - lastDay : '어제 LT', - lastWeek : '지난주 dddd LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s 후', - past : '%s 전', - s : '몇초', - ss : '%d초', - m : '일분', - mm : '%d분', - h : '한시간', - hh : '%d시간', - d : '하루', - dd : '%d일', - M : '한달', - MM : '%d달', - y : '일년', - yy : '%d년' - }, - ordinal : '%d일', - meridiemParse : /(오전|오후)/, - isPM : function (token) { - return token === '오후'; - } - }); -})); -// moment.js locale configuration -// locale : Luxembourgish (lb) -// author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz - -// Note: Luxembourgish has a very particular phonological rule ('Eifeler Regel') that causes the -// deletion of the final 'n' in certain contexts. That's what the 'eifelerRegelAppliesToWeekday' -// and 'eifelerRegelAppliesToNumber' methods are meant for - -(function (factory) { - factory(moment); -}(function (moment) { - function processRelativeTime(number, withoutSuffix, key, isFuture) { - var format = { - 'm': ['eng Minutt', 'enger Minutt'], - 'h': ['eng Stonn', 'enger Stonn'], - 'd': ['een Dag', 'engem Dag'], - 'M': ['ee Mount', 'engem Mount'], - 'y': ['ee Joer', 'engem Joer'] - }; - return withoutSuffix ? format[key][0] : format[key][1]; - } - - function processFutureTime(string) { - var number = string.substr(0, string.indexOf(' ')); - if (eifelerRegelAppliesToNumber(number)) { - return 'a ' + string; - } - return 'an ' + string; - } - - function processPastTime(string) { - var number = string.substr(0, string.indexOf(' ')); - if (eifelerRegelAppliesToNumber(number)) { - return 'viru ' + string; - } - return 'virun ' + string; - } - - /** - * Returns true if the word before the given number loses the '-n' ending. - * e.g. 'an 10 Deeg' but 'a 5 Deeg' - * - * @param number {integer} - * @returns {boolean} - */ - function eifelerRegelAppliesToNumber(number) { - number = parseInt(number, 10); - if (isNaN(number)) { - return false; - } - if (number < 0) { - // Negative Number --> always true - return true; - } else if (number < 10) { - // Only 1 digit - if (4 <= number && number <= 7) { - return true; - } - return false; - } else if (number < 100) { - // 2 digits - var lastDigit = number % 10, firstDigit = number / 10; - if (lastDigit === 0) { - return eifelerRegelAppliesToNumber(firstDigit); - } - return eifelerRegelAppliesToNumber(lastDigit); - } else if (number < 10000) { - // 3 or 4 digits --> recursively check first digit - while (number >= 10) { - number = number / 10; - } - return eifelerRegelAppliesToNumber(number); - } else { - // Anything larger than 4 digits: recursively check first n-3 digits - number = number / 1000; - return eifelerRegelAppliesToNumber(number); - } - } - - return moment.defineLocale('lb', { - months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), - monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), - weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), - weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), - weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), - longDateFormat: { - LT: 'H:mm [Auer]', - L: 'DD.MM.YYYY', - LL: 'D. MMMM YYYY', - LLL: 'D. MMMM YYYY LT', - LLLL: 'dddd, D. MMMM YYYY LT' - }, - calendar: { - sameDay: '[Haut um] LT', - sameElse: 'L', - nextDay: '[Muer um] LT', - nextWeek: 'dddd [um] LT', - lastDay: '[Gëschter um] LT', - lastWeek: function () { - // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule - switch (this.day()) { - case 2: - case 4: - return '[Leschten] dddd [um] LT'; - default: - return '[Leschte] dddd [um] LT'; - } - } - }, - relativeTime : { - future : processFutureTime, - past : processPastTime, - s : 'e puer Sekonnen', - m : processRelativeTime, - mm : '%d Minutten', - h : processRelativeTime, - hh : '%d Stonnen', - d : processRelativeTime, - dd : '%d Deeg', - M : processRelativeTime, - MM : '%d Méint', - y : processRelativeTime, - yy : '%d Joer' - }, - ordinal: '%d.', - week: { - dow: 1, // Monday is the first day of the week. - doy: 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Lithuanian (lt) -// author : Mindaugas Mozūras : https://github.com/mmozuras - -(function (factory) { - factory(moment); -}(function (moment) { - var units = { - 'm' : 'minutė_minutės_minutę', - 'mm': 'minutės_minučių_minutes', - 'h' : 'valanda_valandos_valandą', - 'hh': 'valandos_valandų_valandas', - 'd' : 'diena_dienos_dieną', - 'dd': 'dienos_dienų_dienas', - 'M' : 'mėnuo_mėnesio_mėnesį', - 'MM': 'mėnesiai_mėnesių_mėnesius', - 'y' : 'metai_metų_metus', - 'yy': 'metai_metų_metus' - }, - weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'); - - function translateSeconds(number, withoutSuffix, key, isFuture) { - if (withoutSuffix) { - return 'kelios sekundės'; - } else { - return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; - } - } - - function translateSingular(number, withoutSuffix, key, isFuture) { - return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); - } - - function special(number) { - return number % 10 === 0 || (number > 10 && number < 20); - } - - function forms(key) { - return units[key].split('_'); - } - - function translate(number, withoutSuffix, key, isFuture) { - var result = number + ' '; - if (number === 1) { - return result + translateSingular(number, withoutSuffix, key[0], isFuture); - } else if (withoutSuffix) { - return result + (special(number) ? forms(key)[1] : forms(key)[0]); - } else { - if (isFuture) { - return result + forms(key)[1]; - } else { - return result + (special(number) ? forms(key)[1] : forms(key)[2]); - } - } - } - - function relativeWeekDay(moment, format) { - var nominative = format.indexOf('dddd HH:mm') === -1, - weekDay = weekDays[moment.day()]; - - return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į'; - } - - return moment.defineLocale('lt', { - months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), - monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), - weekdays : relativeWeekDay, - weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), - weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'YYYY-MM-DD', - LL : 'YYYY [m.] MMMM D [d.]', - LLL : 'YYYY [m.] MMMM D [d.], LT [val.]', - LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]', - l : 'YYYY-MM-DD', - ll : 'YYYY [m.] MMMM D [d.]', - lll : 'YYYY [m.] MMMM D [d.], LT [val.]', - llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]' - }, - calendar : { - sameDay : '[Šiandien] LT', - nextDay : '[Rytoj] LT', - nextWeek : 'dddd LT', - lastDay : '[Vakar] LT', - lastWeek : '[Praėjusį] dddd LT', - sameElse : 'L' - }, - relativeTime : { - future : 'po %s', - past : 'prieš %s', - s : translateSeconds, - m : translateSingular, - mm : translate, - h : translateSingular, - hh : translate, - d : translateSingular, - dd : translate, - M : translateSingular, - MM : translate, - y : translateSingular, - yy : translate - }, - ordinal : function (number) { - return number + '-oji'; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : latvian (lv) -// author : Kristaps Karlsons : https://github.com/skakri - -(function (factory) { - factory(moment); -}(function (moment) { - var units = { - 'mm': 'minūti_minūtes_minūte_minūtes', - 'hh': 'stundu_stundas_stunda_stundas', - 'dd': 'dienu_dienas_diena_dienas', - 'MM': 'mēnesi_mēnešus_mēnesis_mēneši', - 'yy': 'gadu_gadus_gads_gadi' - }; - - function format(word, number, withoutSuffix) { - var forms = word.split('_'); - if (withoutSuffix) { - return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; - } else { - return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; - } - } - - function relativeTimeWithPlural(number, withoutSuffix, key) { - return number + ' ' + format(units[key], number, withoutSuffix); - } - - return moment.defineLocale('lv', { - months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'), - monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'), - weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'), - weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'), - weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'YYYY. [gada] D. MMMM', - LLL : 'YYYY. [gada] D. MMMM, LT', - LLLL : 'YYYY. [gada] D. MMMM, dddd, LT' - }, - calendar : { - sameDay : '[Šodien pulksten] LT', - nextDay : '[Rīt pulksten] LT', - nextWeek : 'dddd [pulksten] LT', - lastDay : '[Vakar pulksten] LT', - lastWeek : '[Pagājušā] dddd [pulksten] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s vēlāk', - past : '%s agrāk', - s : 'dažas sekundes', - m : 'minūti', - mm : relativeTimeWithPlural, - h : 'stundu', - hh : relativeTimeWithPlural, - d : 'dienu', - dd : relativeTimeWithPlural, - M : 'mēnesi', - MM : relativeTimeWithPlural, - y : 'gadu', - yy : relativeTimeWithPlural - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : macedonian (mk) -// author : Borislav Mickov : https://github.com/B0k0 - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('mk', { - months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), - monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), - weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), - weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), - weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'D.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Денес во] LT', - nextDay : '[Утре во] LT', - nextWeek : 'dddd [во] LT', - lastDay : '[Вчера во] LT', - lastWeek : function () { - switch (this.day()) { - case 0: - case 3: - case 6: - return '[Во изминатата] dddd [во] LT'; - case 1: - case 2: - case 4: - case 5: - return '[Во изминатиот] dddd [во] LT'; - } - }, - sameElse : 'L' - }, - relativeTime : { - future : 'после %s', - past : 'пред %s', - s : 'неколку секунди', - m : 'минута', - mm : '%d минути', - h : 'час', - hh : '%d часа', - d : 'ден', - dd : '%d дена', - M : 'месец', - MM : '%d месеци', - y : 'година', - yy : '%d години' - }, - ordinal : function (number) { - var lastDigit = number % 10, - last2Digits = number % 100; - if (number === 0) { - return number + '-ев'; - } else if (last2Digits === 0) { - return number + '-ен'; - } else if (last2Digits > 10 && last2Digits < 20) { - return number + '-ти'; - } else if (lastDigit === 1) { - return number + '-ви'; - } else if (lastDigit === 2) { - return number + '-ри'; - } else if (lastDigit === 7 || lastDigit === 8) { - return number + '-ми'; - } else { - return number + '-ти'; - } - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : malayalam (ml) -// author : Floyd Pink : https://github.com/floydpink - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ml', { - months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), - monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), - weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), - weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), - weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), - longDateFormat : { - LT : 'A h:mm -നു', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[ഇന്ന്] LT', - nextDay : '[നാളെ] LT', - nextWeek : 'dddd, LT', - lastDay : '[ഇന്നലെ] LT', - lastWeek : '[കഴിഞ്ഞ] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s കഴിഞ്ഞ്', - past : '%s മുൻപ്', - s : 'അൽപ നിമിഷങ്ങൾ', - m : 'ഒരു മിനിറ്റ്', - mm : '%d മിനിറ്റ്', - h : 'ഒരു മണിക്കൂർ', - hh : '%d മണിക്കൂർ', - d : 'ഒരു ദിവസം', - dd : '%d ദിവസം', - M : 'ഒരു മാസം', - MM : '%d മാസം', - y : 'ഒരു വർഷം', - yy : '%d വർഷം' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'രാത്രി'; - } else if (hour < 12) { - return 'രാവിലെ'; - } else if (hour < 17) { - return 'ഉച്ച കഴിഞ്ഞ്'; - } else if (hour < 20) { - return 'വൈകുന്നേരം'; - } else { - return 'രാത്രി'; - } - } - }); -})); -// moment.js locale configuration -// locale : Marathi (mr) -// author : Harshad Kale : https://github.com/kalehv - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '१', - '2': '२', - '3': '३', - '4': '४', - '5': '५', - '6': '६', - '7': '७', - '8': '८', - '9': '९', - '0': '०' - }, - numberMap = { - '१': '1', - '२': '2', - '३': '3', - '४': '4', - '५': '5', - '६': '6', - '७': '7', - '८': '8', - '९': '9', - '०': '0' - }; - - return moment.defineLocale('mr', { - months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), - monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), - weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), - weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), - weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), - longDateFormat : { - LT : 'A h:mm वाजता', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[आज] LT', - nextDay : '[उद्या] LT', - nextWeek : 'dddd, LT', - lastDay : '[काल] LT', - lastWeek: '[मागील] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s नंतर', - past : '%s पूर्वी', - s : 'सेकंद', - m: 'एक मिनिट', - mm: '%d मिनिटे', - h : 'एक तास', - hh : '%d तास', - d : 'एक दिवस', - dd : '%d दिवस', - M : 'एक महिना', - MM : '%d महिने', - y : 'एक वर्ष', - yy : '%d वर्षे' - }, - preparse: function (string) { - return string.replace(/[१२३४५६७८९०]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - meridiem: function (hour, minute, isLower) - { - if (hour < 4) { - return 'रात्री'; - } else if (hour < 10) { - return 'सकाळी'; - } else if (hour < 17) { - return 'दुपारी'; - } else if (hour < 20) { - return 'सायंकाळी'; - } else { - return 'रात्री'; - } - }, - week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Bahasa Malaysia (ms-MY) -// author : Weldan Jamili : https://github.com/weldan - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('ms-my', { - months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), - monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), - weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), - weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), - weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), - longDateFormat : { - LT : 'HH.mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY [pukul] LT', - LLLL : 'dddd, D MMMM YYYY [pukul] LT' - }, - meridiem : function (hours, minutes, isLower) { - if (hours < 11) { - return 'pagi'; - } else if (hours < 15) { - return 'tengahari'; - } else if (hours < 19) { - return 'petang'; - } else { - return 'malam'; - } - }, - calendar : { - sameDay : '[Hari ini pukul] LT', - nextDay : '[Esok pukul] LT', - nextWeek : 'dddd [pukul] LT', - lastDay : '[Kelmarin pukul] LT', - lastWeek : 'dddd [lepas pukul] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'dalam %s', - past : '%s yang lepas', - s : 'beberapa saat', - m : 'seminit', - mm : '%d minit', - h : 'sejam', - hh : '%d jam', - d : 'sehari', - dd : '%d hari', - M : 'sebulan', - MM : '%d bulan', - y : 'setahun', - yy : '%d tahun' - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Burmese (my) -// author : Squar team, mysquar.com - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '၁', - '2': '၂', - '3': '၃', - '4': '၄', - '5': '၅', - '6': '၆', - '7': '၇', - '8': '၈', - '9': '၉', - '0': '၀' - }, numberMap = { - '၁': '1', - '၂': '2', - '၃': '3', - '၄': '4', - '၅': '5', - '၆': '6', - '၇': '7', - '၈': '8', - '၉': '9', - '၀': '0' - }; - return moment.defineLocale('my', { - months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), - monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), - weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), - weekdaysShort: 'နွေ_လာ_င်္ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), - weekdaysMin: 'နွေ_လာ_င်္ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), - longDateFormat: { - LT: 'HH:mm', - L: 'DD/MM/YYYY', - LL: 'D MMMM YYYY', - LLL: 'D MMMM YYYY LT', - LLLL: 'dddd D MMMM YYYY LT' - }, - calendar: { - sameDay: '[ယနေ.] LT [မှာ]', - nextDay: '[မနက်ဖြန်] LT [မှာ]', - nextWeek: 'dddd LT [မှာ]', - lastDay: '[မနေ.က] LT [မှာ]', - lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', - sameElse: 'L' - }, - relativeTime: { - future: 'လာမည့် %s မှာ', - past: 'လွန်ခဲ့သော %s က', - s: 'စက္ကန်.အနည်းငယ်', - m: 'တစ်မိနစ်', - mm: '%d မိနစ်', - h: 'တစ်နာရီ', - hh: '%d နာရီ', - d: 'တစ်ရက်', - dd: '%d ရက်', - M: 'တစ်လ', - MM: '%d လ', - y: 'တစ်နှစ်', - yy: '%d နှစ်' - }, - preparse: function (string) { - return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - week: { - dow: 1, // Monday is the first day of the week. - doy: 4 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : norwegian bokmål (nb) -// authors : Espen Hovlandsdal : https://github.com/rexxars -// Sigurd Gartmann : https://github.com/sigurdga - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('nb', { - months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), - monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), - weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), - weekdaysShort : 'søn_man_tirs_ons_tors_fre_lør'.split('_'), - weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), - longDateFormat : { - LT : 'H.mm', - L : 'DD.MM.YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY [kl.] LT', - LLLL : 'dddd D. MMMM YYYY [kl.] LT' - }, - calendar : { - sameDay: '[i dag kl.] LT', - nextDay: '[i morgen kl.] LT', - nextWeek: 'dddd [kl.] LT', - lastDay: '[i går kl.] LT', - lastWeek: '[forrige] dddd [kl.] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'om %s', - past : 'for %s siden', - s : 'noen sekunder', - m : 'ett minutt', - mm : '%d minutter', - h : 'en time', - hh : '%d timer', - d : 'en dag', - dd : '%d dager', - M : 'en måned', - MM : '%d måneder', - y : 'ett år', - yy : '%d år' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : nepali/nepalese -// author : suvash : https://github.com/suvash - -(function (factory) { - factory(moment); -}(function (moment) { - var symbolMap = { - '1': '१', - '2': '२', - '3': '३', - '4': '४', - '5': '५', - '6': '६', - '7': '७', - '8': '८', - '9': '९', - '0': '०' - }, - numberMap = { - '१': '1', - '२': '2', - '३': '3', - '४': '4', - '५': '5', - '६': '6', - '७': '7', - '८': '8', - '९': '9', - '०': '0' - }; - - return moment.defineLocale('ne', { - months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), - monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), - weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), - weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), - weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'), - longDateFormat : { - LT : 'Aको h:mm बजे', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - preparse: function (string) { - return string.replace(/[१२३४५६७८९०]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - }, - meridiem : function (hour, minute, isLower) { - if (hour < 3) { - return 'राती'; - } else if (hour < 10) { - return 'बिहान'; - } else if (hour < 15) { - return 'दिउँसो'; - } else if (hour < 18) { - return 'बेलुका'; - } else if (hour < 20) { - return 'साँझ'; - } else { - return 'राती'; - } - }, - calendar : { - sameDay : '[आज] LT', - nextDay : '[भोली] LT', - nextWeek : '[आउँदो] dddd[,] LT', - lastDay : '[हिजो] LT', - lastWeek : '[गएको] dddd[,] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%sमा', - past : '%s अगाडी', - s : 'केही समय', - m : 'एक मिनेट', - mm : '%d मिनेट', - h : 'एक घण्टा', - hh : '%d घण्टा', - d : 'एक दिन', - dd : '%d दिन', - M : 'एक महिना', - MM : '%d महिना', - y : 'एक बर्ष', - yy : '%d बर्ष' - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : dutch (nl) -// author : Joris Röling : https://github.com/jjupiter - -(function (factory) { - factory(moment); -}(function (moment) { - var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), - monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); - - return moment.defineLocale('nl', { - months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), - monthsShort : function (m, format) { - if (/-MMM-/.test(format)) { - return monthsShortWithoutDots[m.month()]; - } else { - return monthsShortWithDots[m.month()]; - } - }, - weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), - weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), - weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD-MM-YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[vandaag om] LT', - nextDay: '[morgen om] LT', - nextWeek: 'dddd [om] LT', - lastDay: '[gisteren om] LT', - lastWeek: '[afgelopen] dddd [om] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'over %s', - past : '%s geleden', - s : 'een paar seconden', - m : 'één minuut', - mm : '%d minuten', - h : 'één uur', - hh : '%d uur', - d : 'één dag', - dd : '%d dagen', - M : 'één maand', - MM : '%d maanden', - y : 'één jaar', - yy : '%d jaar' - }, - ordinal : function (number) { - return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : norwegian nynorsk (nn) -// author : https://github.com/mechuwind - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('nn', { - months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), - monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), - weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), - weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), - weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[I dag klokka] LT', - nextDay: '[I morgon klokka] LT', - nextWeek: 'dddd [klokka] LT', - lastDay: '[I går klokka] LT', - lastWeek: '[Føregåande] dddd [klokka] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'om %s', - past : 'for %s sidan', - s : 'nokre sekund', - m : 'eit minutt', - mm : '%d minutt', - h : 'ein time', - hh : '%d timar', - d : 'ein dag', - dd : '%d dagar', - M : 'ein månad', - MM : '%d månader', - y : 'eit år', - yy : '%d år' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : polish (pl) -// author : Rafal Hirsz : https://github.com/evoL - -(function (factory) { - factory(moment); -}(function (moment) { - var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'), - monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_'); - - function plural(n) { - return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); - } - - function translate(number, withoutSuffix, key) { - var result = number + ' '; - switch (key) { - case 'm': - return withoutSuffix ? 'minuta' : 'minutę'; - case 'mm': - return result + (plural(number) ? 'minuty' : 'minut'); - case 'h': - return withoutSuffix ? 'godzina' : 'godzinę'; - case 'hh': - return result + (plural(number) ? 'godziny' : 'godzin'); - case 'MM': - return result + (plural(number) ? 'miesiące' : 'miesięcy'); - case 'yy': - return result + (plural(number) ? 'lata' : 'lat'); - } - } - - return moment.defineLocale('pl', { - months : function (momentToFormat, format) { - if (/D MMMM/.test(format)) { - return monthsSubjective[momentToFormat.month()]; - } else { - return monthsNominative[momentToFormat.month()]; - } - }, - monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'), - weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'), - weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'), - weekdaysMin : 'N_Pn_Wt_Śr_Cz_Pt_So'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay: '[Dziś o] LT', - nextDay: '[Jutro o] LT', - nextWeek: '[W] dddd [o] LT', - lastDay: '[Wczoraj o] LT', - lastWeek: function () { - switch (this.day()) { - case 0: - return '[W zeszłą niedzielę o] LT'; - case 3: - return '[W zeszłą środę o] LT'; - case 6: - return '[W zeszłą sobotę o] LT'; - default: - return '[W zeszły] dddd [o] LT'; - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'za %s', - past : '%s temu', - s : 'kilka sekund', - m : translate, - mm : translate, - h : translate, - hh : translate, - d : '1 dzień', - dd : '%d dni', - M : 'miesiąc', - MM : translate, - y : 'rok', - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : brazilian portuguese (pt-br) -// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('pt-br', { - months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'), - monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'), - weekdays : 'domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado'.split('_'), - weekdaysShort : 'dom_seg_ter_qua_qui_sex_sáb'.split('_'), - weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D [de] MMMM [de] YYYY', - LLL : 'D [de] MMMM [de] YYYY [às] LT', - LLLL : 'dddd, D [de] MMMM [de] YYYY [às] LT' - }, - calendar : { - sameDay: '[Hoje às] LT', - nextDay: '[Amanhã às] LT', - nextWeek: 'dddd [às] LT', - lastDay: '[Ontem às] LT', - lastWeek: function () { - return (this.day() === 0 || this.day() === 6) ? - '[Último] dddd [às] LT' : // Saturday + Sunday - '[Última] dddd [às] LT'; // Monday - Friday - }, - sameElse: 'L' - }, - relativeTime : { - future : 'em %s', - past : '%s atrás', - s : 'segundos', - m : 'um minuto', - mm : '%d minutos', - h : 'uma hora', - hh : '%d horas', - d : 'um dia', - dd : '%d dias', - M : 'um mês', - MM : '%d meses', - y : 'um ano', - yy : '%d anos' - }, - ordinal : '%dº' - }); -})); -// moment.js locale configuration -// locale : portuguese (pt) -// author : Jefferson : https://github.com/jalex79 - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('pt', { - months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'), - monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'), - weekdays : 'domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado'.split('_'), - weekdaysShort : 'dom_seg_ter_qua_qui_sex_sáb'.split('_'), - weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D [de] MMMM [de] YYYY', - LLL : 'D [de] MMMM [de] YYYY LT', - LLLL : 'dddd, D [de] MMMM [de] YYYY LT' - }, - calendar : { - sameDay: '[Hoje às] LT', - nextDay: '[Amanhã às] LT', - nextWeek: 'dddd [às] LT', - lastDay: '[Ontem às] LT', - lastWeek: function () { - return (this.day() === 0 || this.day() === 6) ? - '[Último] dddd [às] LT' : // Saturday + Sunday - '[Última] dddd [às] LT'; // Monday - Friday - }, - sameElse: 'L' - }, - relativeTime : { - future : 'em %s', - past : 'há %s', - s : 'segundos', - m : 'um minuto', - mm : '%d minutos', - h : 'uma hora', - hh : '%d horas', - d : 'um dia', - dd : '%d dias', - M : 'um mês', - MM : '%d meses', - y : 'um ano', - yy : '%d anos' - }, - ordinal : '%dº', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : romanian (ro) -// author : Vlad Gurdiga : https://github.com/gurdiga -// author : Valentin Agachi : https://github.com/avaly - -(function (factory) { - factory(moment); -}(function (moment) { - function relativeTimeWithPlural(number, withoutSuffix, key) { - var format = { - 'mm': 'minute', - 'hh': 'ore', - 'dd': 'zile', - 'MM': 'luni', - 'yy': 'ani' - }, - separator = ' '; - if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { - separator = ' de '; - } - - return number + separator + format[key]; - } - - return moment.defineLocale('ro', { - months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), - monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), - weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), - weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), - weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY H:mm', - LLLL : 'dddd, D MMMM YYYY H:mm' - }, - calendar : { - sameDay: '[azi la] LT', - nextDay: '[mâine la] LT', - nextWeek: 'dddd [la] LT', - lastDay: '[ieri la] LT', - lastWeek: '[fosta] dddd [la] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'peste %s', - past : '%s în urmă', - s : 'câteva secunde', - m : 'un minut', - mm : relativeTimeWithPlural, - h : 'o oră', - hh : relativeTimeWithPlural, - d : 'o zi', - dd : relativeTimeWithPlural, - M : 'o lună', - MM : relativeTimeWithPlural, - y : 'un an', - yy : relativeTimeWithPlural - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : russian (ru) -// author : Viktorminator : https://github.com/Viktorminator -// Author : Menelion Elensúle : https://github.com/Oire - -(function (factory) { - factory(moment); -}(function (moment) { - function plural(word, num) { - var forms = word.split('_'); - return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); - } - - function relativeTimeWithPlural(number, withoutSuffix, key) { - var format = { - 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', - 'hh': 'час_часа_часов', - 'dd': 'день_дня_дней', - 'MM': 'месяц_месяца_месяцев', - 'yy': 'год_года_лет' - }; - if (key === 'm') { - return withoutSuffix ? 'минута' : 'минуту'; - } - else { - return number + ' ' + plural(format[key], +number); - } - } - - function monthsCaseReplace(m, format) { - var months = { - 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), - 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') - }, - - nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return months[nounCase][m.month()]; - } - - function monthsShortCaseReplace(m, format) { - var monthsShort = { - 'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), - 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') - }, - - nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return monthsShort[nounCase][m.month()]; - } - - function weekdaysCaseReplace(m, format) { - var weekdays = { - 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), - 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') - }, - - nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ? - 'accusative' : - 'nominative'; - - return weekdays[nounCase][m.day()]; - } - - return moment.defineLocale('ru', { - months : monthsCaseReplace, - monthsShort : monthsShortCaseReplace, - weekdays : weekdaysCaseReplace, - weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), - weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), - monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i], - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY г.', - LLL : 'D MMMM YYYY г., LT', - LLLL : 'dddd, D MMMM YYYY г., LT' - }, - calendar : { - sameDay: '[Сегодня в] LT', - nextDay: '[Завтра в] LT', - lastDay: '[Вчера в] LT', - nextWeek: function () { - return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; - }, - lastWeek: function () { - switch (this.day()) { - case 0: - return '[В прошлое] dddd [в] LT'; - case 1: - case 2: - case 4: - return '[В прошлый] dddd [в] LT'; - case 3: - case 5: - case 6: - return '[В прошлую] dddd [в] LT'; - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'через %s', - past : '%s назад', - s : 'несколько секунд', - m : relativeTimeWithPlural, - mm : relativeTimeWithPlural, - h : 'час', - hh : relativeTimeWithPlural, - d : 'день', - dd : relativeTimeWithPlural, - M : 'месяц', - MM : relativeTimeWithPlural, - y : 'год', - yy : relativeTimeWithPlural - }, - - meridiemParse: /ночи|утра|дня|вечера/i, - isPM : function (input) { - return /^(дня|вечера)$/.test(input); - }, - - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'ночи'; - } else if (hour < 12) { - return 'утра'; - } else if (hour < 17) { - return 'дня'; - } else { - return 'вечера'; - } - }, - - ordinal: function (number, period) { - switch (period) { - case 'M': - case 'd': - case 'DDD': - return number + '-й'; - case 'D': - return number + '-го'; - case 'w': - case 'W': - return number + '-я'; - default: - return number; - } - }, - - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : slovak (sk) -// author : Martin Minka : https://github.com/k2s -// based on work of petrbela : https://github.com/petrbela - -(function (factory) { - factory(moment); -}(function (moment) { - var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), - monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); - - function plural(n) { - return (n > 1) && (n < 5); - } - - function translate(number, withoutSuffix, key, isFuture) { - var result = number + ' '; - switch (key) { - case 's': // a few seconds / in a few seconds / a few seconds ago - return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; - case 'm': // a minute / in a minute / a minute ago - return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); - case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'minúty' : 'minút'); - } else { - return result + 'minútami'; - } - break; - case 'h': // an hour / in an hour / an hour ago - return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); - case 'hh': // 9 hours / in 9 hours / 9 hours ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'hodiny' : 'hodín'); - } else { - return result + 'hodinami'; - } - break; - case 'd': // a day / in a day / a day ago - return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; - case 'dd': // 9 days / in 9 days / 9 days ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'dni' : 'dní'); - } else { - return result + 'dňami'; - } - break; - case 'M': // a month / in a month / a month ago - return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; - case 'MM': // 9 months / in 9 months / 9 months ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'mesiace' : 'mesiacov'); - } else { - return result + 'mesiacmi'; - } - break; - case 'y': // a year / in a year / a year ago - return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; - case 'yy': // 9 years / in 9 years / 9 years ago - if (withoutSuffix || isFuture) { - return result + (plural(number) ? 'roky' : 'rokov'); - } else { - return result + 'rokmi'; - } - break; - } - } - - return moment.defineLocale('sk', { - months : months, - monthsShort : monthsShort, - monthsParse : (function (months, monthsShort) { - var i, _monthsParse = []; - for (i = 0; i < 12; i++) { - // use custom parser to solve problem with July (červenec) - _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); - } - return _monthsParse; - }(months, monthsShort)), - weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'), - weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'), - weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'), - longDateFormat : { - LT: 'H:mm', - L : 'DD.MM.YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd D. MMMM YYYY LT' - }, - calendar : { - sameDay: '[dnes o] LT', - nextDay: '[zajtra o] LT', - nextWeek: function () { - switch (this.day()) { - case 0: - return '[v nedeľu o] LT'; - case 1: - case 2: - return '[v] dddd [o] LT'; - case 3: - return '[v stredu o] LT'; - case 4: - return '[vo štvrtok o] LT'; - case 5: - return '[v piatok o] LT'; - case 6: - return '[v sobotu o] LT'; - } - }, - lastDay: '[včera o] LT', - lastWeek: function () { - switch (this.day()) { - case 0: - return '[minulú nedeľu o] LT'; - case 1: - case 2: - return '[minulý] dddd [o] LT'; - case 3: - return '[minulú stredu o] LT'; - case 4: - case 5: - return '[minulý] dddd [o] LT'; - case 6: - return '[minulú sobotu o] LT'; - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'za %s', - past : 'pred %s', - s : translate, - m : translate, - mm : translate, - h : translate, - hh : translate, - d : translate, - dd : translate, - M : translate, - MM : translate, - y : translate, - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : slovenian (sl) -// author : Robert Sedovšek : https://github.com/sedovsek - -(function (factory) { - factory(moment); -}(function (moment) { - function translate(number, withoutSuffix, key) { - var result = number + ' '; - switch (key) { - case 'm': - return withoutSuffix ? 'ena minuta' : 'eno minuto'; - case 'mm': - if (number === 1) { - result += 'minuta'; - } else if (number === 2) { - result += 'minuti'; - } else if (number === 3 || number === 4) { - result += 'minute'; - } else { - result += 'minut'; - } - return result; - case 'h': - return withoutSuffix ? 'ena ura' : 'eno uro'; - case 'hh': - if (number === 1) { - result += 'ura'; - } else if (number === 2) { - result += 'uri'; - } else if (number === 3 || number === 4) { - result += 'ure'; - } else { - result += 'ur'; - } - return result; - case 'dd': - if (number === 1) { - result += 'dan'; - } else { - result += 'dni'; - } - return result; - case 'MM': - if (number === 1) { - result += 'mesec'; - } else if (number === 2) { - result += 'meseca'; - } else if (number === 3 || number === 4) { - result += 'mesece'; - } else { - result += 'mesecev'; - } - return result; - case 'yy': - if (number === 1) { - result += 'leto'; - } else if (number === 2) { - result += 'leti'; - } else if (number === 3 || number === 4) { - result += 'leta'; - } else { - result += 'let'; - } - return result; - } - } - - return moment.defineLocale('sl', { - months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'), - monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), - weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'), - weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'), - weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'), - longDateFormat : { - LT : 'H:mm', - L : 'DD. MM. YYYY', - LL : 'D. MMMM YYYY', - LLL : 'D. MMMM YYYY LT', - LLLL : 'dddd, D. MMMM YYYY LT' - }, - calendar : { - sameDay : '[danes ob] LT', - nextDay : '[jutri ob] LT', - - nextWeek : function () { - switch (this.day()) { - case 0: - return '[v] [nedeljo] [ob] LT'; - case 3: - return '[v] [sredo] [ob] LT'; - case 6: - return '[v] [soboto] [ob] LT'; - case 1: - case 2: - case 4: - case 5: - return '[v] dddd [ob] LT'; - } - }, - lastDay : '[včeraj ob] LT', - lastWeek : function () { - switch (this.day()) { - case 0: - case 3: - case 6: - return '[prejšnja] dddd [ob] LT'; - case 1: - case 2: - case 4: - case 5: - return '[prejšnji] dddd [ob] LT'; - } - }, - sameElse : 'L' - }, - relativeTime : { - future : 'čez %s', - past : '%s nazaj', - s : 'nekaj sekund', - m : translate, - mm : translate, - h : translate, - hh : translate, - d : 'en dan', - dd : translate, - M : 'en mesec', - MM : translate, - y : 'eno leto', - yy : translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Albanian (sq) -// author : Flakërim Ismani : https://github.com/flakerimi -// author: Menelion Elensúle: https://github.com/Oire (tests) -// author : Oerd Cukalla : https://github.com/oerd (fixes) - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('sq', { - months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), - monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), - weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), - weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), - weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), - meridiem : function (hours, minutes, isLower) { - return hours < 12 ? 'PD' : 'MD'; - }, - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[Sot në] LT', - nextDay : '[Nesër në] LT', - nextWeek : 'dddd [në] LT', - lastDay : '[Dje në] LT', - lastWeek : 'dddd [e kaluar në] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'në %s', - past : '%s më parë', - s : 'disa sekonda', - m : 'një minutë', - mm : '%d minuta', - h : 'një orë', - hh : '%d orë', - d : 'një ditë', - dd : '%d ditë', - M : 'një muaj', - MM : '%d muaj', - y : 'një vit', - yy : '%d vite' - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Serbian-cyrillic (sr-cyrl) -// author : Milan Janačković : https://github.com/milan-j - -(function (factory) { - factory(moment); -}(function (moment) { - var translator = { - words: { //Different grammatical cases - m: ['један минут', 'једне минуте'], - mm: ['минут', 'минуте', 'минута'], - h: ['један сат', 'једног сата'], - hh: ['сат', 'сата', 'сати'], - dd: ['дан', 'дана', 'дана'], - MM: ['месец', 'месеца', 'месеци'], - yy: ['година', 'године', 'година'] - }, - correctGrammaticalCase: function (number, wordKey) { - return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); - }, - translate: function (number, withoutSuffix, key) { - var wordKey = translator.words[key]; - if (key.length === 1) { - return withoutSuffix ? wordKey[0] : wordKey[1]; - } else { - return number + ' ' + translator.correctGrammaticalCase(number, wordKey); - } - } - }; - - return moment.defineLocale('sr-cyrl', { - months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], - monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], - weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], - weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], - weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], - longDateFormat: { - LT: 'H:mm', - L: 'DD. MM. YYYY', - LL: 'D. MMMM YYYY', - LLL: 'D. MMMM YYYY LT', - LLLL: 'dddd, D. MMMM YYYY LT' - }, - calendar: { - sameDay: '[данас у] LT', - nextDay: '[сутра у] LT', - - nextWeek: function () { - switch (this.day()) { - case 0: - return '[у] [недељу] [у] LT'; - case 3: - return '[у] [среду] [у] LT'; - case 6: - return '[у] [суботу] [у] LT'; - case 1: - case 2: - case 4: - case 5: - return '[у] dddd [у] LT'; - } - }, - lastDay : '[јуче у] LT', - lastWeek : function () { - var lastWeekDays = [ - '[прошле] [недеље] [у] LT', - '[прошлог] [понедељка] [у] LT', - '[прошлог] [уторка] [у] LT', - '[прошле] [среде] [у] LT', - '[прошлог] [четвртка] [у] LT', - '[прошлог] [петка] [у] LT', - '[прошле] [суботе] [у] LT' - ]; - return lastWeekDays[this.day()]; - }, - sameElse : 'L' - }, - relativeTime : { - future : 'за %s', - past : 'пре %s', - s : 'неколико секунди', - m : translator.translate, - mm : translator.translate, - h : translator.translate, - hh : translator.translate, - d : 'дан', - dd : translator.translate, - M : 'месец', - MM : translator.translate, - y : 'годину', - yy : translator.translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Serbian-latin (sr) -// author : Milan Janačković : https://github.com/milan-j - -(function (factory) { - factory(moment); -}(function (moment) { - var translator = { - words: { //Different grammatical cases - m: ['jedan minut', 'jedne minute'], - mm: ['minut', 'minute', 'minuta'], - h: ['jedan sat', 'jednog sata'], - hh: ['sat', 'sata', 'sati'], - dd: ['dan', 'dana', 'dana'], - MM: ['mesec', 'meseca', 'meseci'], - yy: ['godina', 'godine', 'godina'] - }, - correctGrammaticalCase: function (number, wordKey) { - return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); - }, - translate: function (number, withoutSuffix, key) { - var wordKey = translator.words[key]; - if (key.length === 1) { - return withoutSuffix ? wordKey[0] : wordKey[1]; - } else { - return number + ' ' + translator.correctGrammaticalCase(number, wordKey); - } - } - }; - - return moment.defineLocale('sr', { - months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], - monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], - weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], - weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], - weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], - longDateFormat: { - LT: 'H:mm', - L: 'DD. MM. YYYY', - LL: 'D. MMMM YYYY', - LLL: 'D. MMMM YYYY LT', - LLLL: 'dddd, D. MMMM YYYY LT' - }, - calendar: { - sameDay: '[danas u] LT', - nextDay: '[sutra u] LT', - - nextWeek: function () { - switch (this.day()) { - case 0: - return '[u] [nedelju] [u] LT'; - case 3: - return '[u] [sredu] [u] LT'; - case 6: - return '[u] [subotu] [u] LT'; - case 1: - case 2: - case 4: - case 5: - return '[u] dddd [u] LT'; - } - }, - lastDay : '[juče u] LT', - lastWeek : function () { - var lastWeekDays = [ - '[prošle] [nedelje] [u] LT', - '[prošlog] [ponedeljka] [u] LT', - '[prošlog] [utorka] [u] LT', - '[prošle] [srede] [u] LT', - '[prošlog] [četvrtka] [u] LT', - '[prošlog] [petka] [u] LT', - '[prošle] [subote] [u] LT' - ]; - return lastWeekDays[this.day()]; - }, - sameElse : 'L' - }, - relativeTime : { - future : 'za %s', - past : 'pre %s', - s : 'nekoliko sekundi', - m : translator.translate, - mm : translator.translate, - h : translator.translate, - hh : translator.translate, - d : 'dan', - dd : translator.translate, - M : 'mesec', - MM : translator.translate, - y : 'godinu', - yy : translator.translate - }, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : swedish (sv) -// author : Jens Alm : https://github.com/ulmus - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('sv', { - months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), - monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), - weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), - weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), - weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'YYYY-MM-DD', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[Idag] LT', - nextDay: '[Imorgon] LT', - lastDay: '[Igår] LT', - nextWeek: 'dddd LT', - lastWeek: '[Förra] dddd[en] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'om %s', - past : 'för %s sedan', - s : 'några sekunder', - m : 'en minut', - mm : '%d minuter', - h : 'en timme', - hh : '%d timmar', - d : 'en dag', - dd : '%d dagar', - M : 'en månad', - MM : '%d månader', - y : 'ett år', - yy : '%d år' - }, - ordinal : function (number) { - var b = number % 10, - output = (~~(number % 100 / 10) === 1) ? 'e' : - (b === 1) ? 'a' : - (b === 2) ? 'a' : - (b === 3) ? 'e' : 'e'; - return number + output; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : tamil (ta) -// author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 - -(function (factory) { - factory(moment); -}(function (moment) { - /*var symbolMap = { - '1': '௧', - '2': '௨', - '3': '௩', - '4': '௪', - '5': '௫', - '6': '௬', - '7': '௭', - '8': '௮', - '9': '௯', - '0': '௦' - }, - numberMap = { - '௧': '1', - '௨': '2', - '௩': '3', - '௪': '4', - '௫': '5', - '௬': '6', - '௭': '7', - '௮': '8', - '௯': '9', - '௦': '0' - }; */ - - return moment.defineLocale('ta', { - months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), - monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), - weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), - weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), - weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY, LT', - LLLL : 'dddd, D MMMM YYYY, LT' - }, - calendar : { - sameDay : '[இன்று] LT', - nextDay : '[நாளை] LT', - nextWeek : 'dddd, LT', - lastDay : '[நேற்று] LT', - lastWeek : '[கடந்த வாரம்] dddd, LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s இல்', - past : '%s முன்', - s : 'ஒரு சில விநாடிகள்', - m : 'ஒரு நிமிடம்', - mm : '%d நிமிடங்கள்', - h : 'ஒரு மணி நேரம்', - hh : '%d மணி நேரம்', - d : 'ஒரு நாள்', - dd : '%d நாட்கள்', - M : 'ஒரு மாதம்', - MM : '%d மாதங்கள்', - y : 'ஒரு வருடம்', - yy : '%d ஆண்டுகள்' - }, -/* preparse: function (string) { - return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) { - return numberMap[match]; - }); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }); - },*/ - ordinal : function (number) { - return number + 'வது'; - }, - - - // refer http://ta.wikipedia.org/s/1er1 - - meridiem : function (hour, minute, isLower) { - if (hour >= 6 && hour <= 10) { - return ' காலை'; - } else if (hour >= 10 && hour <= 14) { - return ' நண்பகல்'; - } else if (hour >= 14 && hour <= 18) { - return ' எற்பாடு'; - } else if (hour >= 18 && hour <= 20) { - return ' மாலை'; - } else if (hour >= 20 && hour <= 24) { - return ' இரவு'; - } else if (hour >= 0 && hour <= 6) { - return ' வைகறை'; - } - }, - week : { - dow : 0, // Sunday is the first day of the week. - doy : 6 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : thai (th) -// author : Kridsada Thanabulpong : https://github.com/sirn - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('th', { - months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), - monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), - weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), - weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference - weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), - longDateFormat : { - LT : 'H นาฬิกา m นาที', - L : 'YYYY/MM/DD', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY เวลา LT', - LLLL : 'วันddddที่ D MMMM YYYY เวลา LT' - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return 'ก่อนเที่ยง'; - } else { - return 'หลังเที่ยง'; - } - }, - calendar : { - sameDay : '[วันนี้ เวลา] LT', - nextDay : '[พรุ่งนี้ เวลา] LT', - nextWeek : 'dddd[หน้า เวลา] LT', - lastDay : '[เมื่อวานนี้ เวลา] LT', - lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'อีก %s', - past : '%sที่แล้ว', - s : 'ไม่กี่วินาที', - m : '1 นาที', - mm : '%d นาที', - h : '1 ชั่วโมง', - hh : '%d ชั่วโมง', - d : '1 วัน', - dd : '%d วัน', - M : '1 เดือน', - MM : '%d เดือน', - y : '1 ปี', - yy : '%d ปี' - } - }); -})); -// moment.js locale configuration -// locale : Tagalog/Filipino (tl-ph) -// author : Dan Hagman - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('tl-ph', { - months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), - monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), - weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), - weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), - weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'MM/D/YYYY', - LL : 'MMMM D, YYYY', - LLL : 'MMMM D, YYYY LT', - LLLL : 'dddd, MMMM DD, YYYY LT' - }, - calendar : { - sameDay: '[Ngayon sa] LT', - nextDay: '[Bukas sa] LT', - nextWeek: 'dddd [sa] LT', - lastDay: '[Kahapon sa] LT', - lastWeek: 'dddd [huling linggo] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'sa loob ng %s', - past : '%s ang nakalipas', - s : 'ilang segundo', - m : 'isang minuto', - mm : '%d minuto', - h : 'isang oras', - hh : '%d oras', - d : 'isang araw', - dd : '%d araw', - M : 'isang buwan', - MM : '%d buwan', - y : 'isang taon', - yy : '%d taon' - }, - ordinal : function (number) { - return number; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : turkish (tr) -// authors : Erhan Gundogan : https://github.com/erhangundogan, -// Burak Yiğit Kaya: https://github.com/BYK - -(function (factory) { - factory(moment); -}(function (moment) { - var suffixes = { - 1: '\'inci', - 5: '\'inci', - 8: '\'inci', - 70: '\'inci', - 80: '\'inci', - - 2: '\'nci', - 7: '\'nci', - 20: '\'nci', - 50: '\'nci', - - 3: '\'üncü', - 4: '\'üncü', - 100: '\'üncü', - - 6: '\'ncı', - - 9: '\'uncu', - 10: '\'uncu', - 30: '\'uncu', - - 60: '\'ıncı', - 90: '\'ıncı' - }; - - return moment.defineLocale('tr', { - months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), - monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), - weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), - weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), - weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd, D MMMM YYYY LT' - }, - calendar : { - sameDay : '[bugün saat] LT', - nextDay : '[yarın saat] LT', - nextWeek : '[haftaya] dddd [saat] LT', - lastDay : '[dün] LT', - lastWeek : '[geçen hafta] dddd [saat] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s sonra', - past : '%s önce', - s : 'birkaç saniye', - m : 'bir dakika', - mm : '%d dakika', - h : 'bir saat', - hh : '%d saat', - d : 'bir gün', - dd : '%d gün', - M : 'bir ay', - MM : '%d ay', - y : 'bir yıl', - yy : '%d yıl' - }, - ordinal : function (number) { - if (number === 0) { // special case for zero - return number + '\'ıncı'; - } - var a = number % 10, - b = number % 100 - a, - c = number >= 100 ? 100 : null; - - return number + (suffixes[a] || suffixes[b] || suffixes[c]); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) -// author : Abdel Said : https://github.com/abdelsaid - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('tzm-latn', { - months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), - monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), - weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), - weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), - weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[asdkh g] LT', - nextDay: '[aska g] LT', - nextWeek: 'dddd [g] LT', - lastDay: '[assant g] LT', - lastWeek: 'dddd [g] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'dadkh s yan %s', - past : 'yan %s', - s : 'imik', - m : 'minuḍ', - mm : '%d minuḍ', - h : 'saɛa', - hh : '%d tassaɛin', - d : 'ass', - dd : '%d ossan', - M : 'ayowr', - MM : '%d iyyirn', - y : 'asgas', - yy : '%d isgasn' - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : Morocco Central Atlas Tamaziɣt (tzm) -// author : Abdel Said : https://github.com/abdelsaid - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('tzm', { - months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), - monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), - weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), - weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), - weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'dddd D MMMM YYYY LT' - }, - calendar : { - sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', - nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', - nextWeek: 'dddd [ⴴ] LT', - lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', - lastWeek: 'dddd [ⴴ] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', - past : 'ⵢⴰⵏ %s', - s : 'ⵉⵎⵉⴽ', - m : 'ⵎⵉⵏⵓⴺ', - mm : '%d ⵎⵉⵏⵓⴺ', - h : 'ⵙⴰⵄⴰ', - hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', - d : 'ⴰⵙⵙ', - dd : '%d oⵙⵙⴰⵏ', - M : 'ⴰⵢoⵓⵔ', - MM : '%d ⵉⵢⵢⵉⵔⵏ', - y : 'ⴰⵙⴳⴰⵙ', - yy : '%d ⵉⵙⴳⴰⵙⵏ' - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : ukrainian (uk) -// author : zemlanin : https://github.com/zemlanin -// Author : Menelion Elensúle : https://github.com/Oire - -(function (factory) { - factory(moment); -}(function (moment) { - function plural(word, num) { - var forms = word.split('_'); - return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); - } - - function relativeTimeWithPlural(number, withoutSuffix, key) { - var format = { - 'mm': 'хвилина_хвилини_хвилин', - 'hh': 'година_години_годин', - 'dd': 'день_дні_днів', - 'MM': 'місяць_місяці_місяців', - 'yy': 'рік_роки_років' - }; - if (key === 'm') { - return withoutSuffix ? 'хвилина' : 'хвилину'; - } - else if (key === 'h') { - return withoutSuffix ? 'година' : 'годину'; - } - else { - return number + ' ' + plural(format[key], +number); - } - } - - function monthsCaseReplace(m, format) { - var months = { - 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), - 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') - }, - - nounCase = (/D[oD]? *MMMM?/).test(format) ? - 'accusative' : - 'nominative'; - - return months[nounCase][m.month()]; - } - - function weekdaysCaseReplace(m, format) { - var weekdays = { - 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), - 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), - 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') - }, - - nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? - 'accusative' : - ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? - 'genitive' : - 'nominative'); - - return weekdays[nounCase][m.day()]; - } - - function processHoursFunction(str) { - return function () { - return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; - }; - } - - return moment.defineLocale('uk', { - months : monthsCaseReplace, - monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), - weekdays : weekdaysCaseReplace, - weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), - weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY р.', - LLL : 'D MMMM YYYY р., LT', - LLLL : 'dddd, D MMMM YYYY р., LT' - }, - calendar : { - sameDay: processHoursFunction('[Сьогодні '), - nextDay: processHoursFunction('[Завтра '), - lastDay: processHoursFunction('[Вчора '), - nextWeek: processHoursFunction('[У] dddd ['), - lastWeek: function () { - switch (this.day()) { - case 0: - case 3: - case 5: - case 6: - return processHoursFunction('[Минулої] dddd [').call(this); - case 1: - case 2: - case 4: - return processHoursFunction('[Минулого] dddd [').call(this); - } - }, - sameElse: 'L' - }, - relativeTime : { - future : 'за %s', - past : '%s тому', - s : 'декілька секунд', - m : relativeTimeWithPlural, - mm : relativeTimeWithPlural, - h : 'годину', - hh : relativeTimeWithPlural, - d : 'день', - dd : relativeTimeWithPlural, - M : 'місяць', - MM : relativeTimeWithPlural, - y : 'рік', - yy : relativeTimeWithPlural - }, - - // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason - - meridiem : function (hour, minute, isLower) { - if (hour < 4) { - return 'ночі'; - } else if (hour < 12) { - return 'ранку'; - } else if (hour < 17) { - return 'дня'; - } else { - return 'вечора'; - } - }, - - ordinal: function (number, period) { - switch (period) { - case 'M': - case 'd': - case 'DDD': - case 'w': - case 'W': - return number + '-й'; - case 'D': - return number + '-го'; - default: - return number; - } - }, - - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 1st is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : uzbek (uz) -// author : Sardor Muminov : https://github.com/muminoff - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('uz', { - months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), - monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), - weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), - weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), - weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY LT', - LLLL : 'D MMMM YYYY, dddd LT' - }, - calendar : { - sameDay : '[Бугун соат] LT [да]', - nextDay : '[Эртага] LT [да]', - nextWeek : 'dddd [куни соат] LT [да]', - lastDay : '[Кеча соат] LT [да]', - lastWeek : '[Утган] dddd [куни соат] LT [да]', - sameElse : 'L' - }, - relativeTime : { - future : 'Якин %s ичида', - past : 'Бир неча %s олдин', - s : 'фурсат', - m : 'бир дакика', - mm : '%d дакика', - h : 'бир соат', - hh : '%d соат', - d : 'бир кун', - dd : '%d кун', - M : 'бир ой', - MM : '%d ой', - y : 'бир йил', - yy : '%d йил' - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : vietnamese (vi) -// author : Bang Nguyen : https://github.com/bangnk - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('vi', { - months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), - monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), - weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), - weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), - weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), - longDateFormat : { - LT : 'HH:mm', - L : 'DD/MM/YYYY', - LL : 'D MMMM [năm] YYYY', - LLL : 'D MMMM [năm] YYYY LT', - LLLL : 'dddd, D MMMM [năm] YYYY LT', - l : 'DD/M/YYYY', - ll : 'D MMM YYYY', - lll : 'D MMM YYYY LT', - llll : 'ddd, D MMM YYYY LT' - }, - calendar : { - sameDay: '[Hôm nay lúc] LT', - nextDay: '[Ngày mai lúc] LT', - nextWeek: 'dddd [tuần tới lúc] LT', - lastDay: '[Hôm qua lúc] LT', - lastWeek: 'dddd [tuần rồi lúc] LT', - sameElse: 'L' - }, - relativeTime : { - future : '%s tới', - past : '%s trước', - s : 'vài giây', - m : 'một phút', - mm : '%d phút', - h : 'một giờ', - hh : '%d giờ', - d : 'một ngày', - dd : '%d ngày', - M : 'một tháng', - MM : '%d tháng', - y : 'một năm', - yy : '%d năm' - }, - ordinal : function (number) { - return number; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : chinese (zh-cn) -// author : suupic : https://github.com/suupic -// author : Zeno Zeng : https://github.com/zenozeng - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('zh-cn', { - months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), - monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), - weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), - weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'), - weekdaysMin : '日_一_二_三_四_五_六'.split('_'), - longDateFormat : { - LT : 'Ah点mm', - L : 'YYYY-MM-DD', - LL : 'YYYY年MMMD日', - LLL : 'YYYY年MMMD日LT', - LLLL : 'YYYY年MMMD日ddddLT', - l : 'YYYY-MM-DD', - ll : 'YYYY年MMMD日', - lll : 'YYYY年MMMD日LT', - llll : 'YYYY年MMMD日ddddLT' - }, - meridiem : function (hour, minute, isLower) { - var hm = hour * 100 + minute; - if (hm < 600) { - return '凌晨'; - } else if (hm < 900) { - return '早上'; - } else if (hm < 1130) { - return '上午'; - } else if (hm < 1230) { - return '中午'; - } else if (hm < 1800) { - return '下午'; - } else { - return '晚上'; - } - }, - calendar : { - sameDay : function () { - return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; - }, - nextDay : function () { - return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; - }, - lastDay : function () { - return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; - }, - nextWeek : function () { - var startOfWeek, prefix; - startOfWeek = moment().startOf('week'); - prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; - return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; - }, - lastWeek : function () { - var startOfWeek, prefix; - startOfWeek = moment().startOf('week'); - prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; - return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; - }, - sameElse : 'LL' - }, - ordinal : function (number, period) { - switch (period) { - case 'd': - case 'D': - case 'DDD': - return number + '日'; - case 'M': - return number + '月'; - case 'w': - case 'W': - return number + '周'; - default: - return number; - } - }, - relativeTime : { - future : '%s内', - past : '%s前', - s : '几秒', - m : '1分钟', - mm : '%d分钟', - h : '1小时', - hh : '%d小时', - d : '1天', - dd : '%d天', - M : '1个月', - MM : '%d个月', - y : '1年', - yy : '%d年' - }, - week : { - // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); -})); -// moment.js locale configuration -// locale : traditional chinese (zh-tw) -// author : Ben : https://github.com/ben-lin - -(function (factory) { - factory(moment); -}(function (moment) { - return moment.defineLocale('zh-tw', { - months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), - monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), - weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), - weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'), - weekdaysMin : '日_一_二_三_四_五_六'.split('_'), - longDateFormat : { - LT : 'Ah點mm', - L : 'YYYY年MMMD日', - LL : 'YYYY年MMMD日', - LLL : 'YYYY年MMMD日LT', - LLLL : 'YYYY年MMMD日ddddLT', - l : 'YYYY年MMMD日', - ll : 'YYYY年MMMD日', - lll : 'YYYY年MMMD日LT', - llll : 'YYYY年MMMD日ddddLT' - }, - meridiem : function (hour, minute, isLower) { - var hm = hour * 100 + minute; - if (hm < 900) { - return '早上'; - } else if (hm < 1130) { - return '上午'; - } else if (hm < 1230) { - return '中午'; - } else if (hm < 1800) { - return '下午'; - } else { - return '晚上'; - } - }, - calendar : { - sameDay : '[今天]LT', - nextDay : '[明天]LT', - nextWeek : '[下]ddddLT', - lastDay : '[昨天]LT', - lastWeek : '[上]ddddLT', - sameElse : 'L' - }, - ordinal : function (number, period) { - switch (period) { - case 'd' : - case 'D' : - case 'DDD' : - return number + '日'; - case 'M' : - return number + '月'; - case 'w' : - case 'W' : - return number + '週'; - default : - return number; - } - }, - relativeTime : { - future : '%s內', - past : '%s前', - s : '幾秒', - m : '一分鐘', - mm : '%d分鐘', - h : '一小時', - hh : '%d小時', - d : '一天', - dd : '%d天', - M : '一個月', - MM : '%d個月', - y : '一年', - yy : '%d年' - } - }); -})); - - moment.locale('en'); - - - /************************************ - Exposing Moment - ************************************/ - - function makeGlobal(shouldDeprecate) { - /*global ender:false */ - if (typeof ender !== 'undefined') { - return; - } - oldGlobalMoment = globalScope.moment; - if (shouldDeprecate) { - globalScope.moment = deprecate( - 'Accessing Moment through the global scope is ' + - 'deprecated, and will be removed in an upcoming ' + - 'release.', - moment); - } else { - globalScope.moment = moment; - } - } - - // CommonJS module is defined - if (hasModule) { - module.exports = moment; - } else if (typeof define === 'function' && define.amd) { - define('moment', function (require, exports, module) { - if (module.config && module.config() && module.config().noGlobal === true) { - // release the global variable - globalScope.moment = oldGlobalMoment; - } - - return moment; - }); - makeGlobal(true); - } else { - makeGlobal(); - } -}).call(this); From cff7dbc81a64e93f957eccf4dc5bb8875af7e3c2 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 31 May 2016 15:21:37 +0200 Subject: [PATCH 78/78] Temp u4 8495 (#1293) * U4-8495 Create YML file for AppVeyor * Secret token needs to be in single quotes * Secure token instead of a configuration variable should make the slack notification work * Only post to Slack when build fails --- appveyor.yml | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..db69da4978 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,51 @@ +version: '{build}' +shallow_clone: true +build_script: +- cmd: >- + cd build + + SET "release=" + + FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i" + + SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% + + ECHO %PATH% + + + ECHO Building Release %release% build%APPVEYOR_BUILD_NUMBER% + + + SET nuGetFolder=%CD%\..\src\packages\ + + ..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL + + ..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet + + + IF EXIST ..\src\umbraco.businesslogic\packages.config ..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet + + ..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet + + + SET MSBUILD="C:\Program Files (x86)\MSBuild\14.0\Bin\MsBuild.exe" + + %MSBUILD% "../src/Umbraco.Tests/Umbraco.Tests.csproj" /verbosity:minimal + + + build.bat %release% build%APPVEYOR_BUILD_NUMBER% + + + ECHO %PATH% +test: + assemblies: src\Umbraco.Tests\bin\Debug\Umbraco.Tests.dll +artifacts: +- path: build\UmbracoCms.* +notifications: +- provider: Slack + auth_token: + secure: v2csJi2V5ghR0rPdODK8GJdOGNCA+XaK84iQ9MdPOClqB+VU+40ybdKp6gPirGSH + channel: '#build-umbraco-core' + on_build_success: false + on_build_failure: true + on_build_status_changed: false \ No newline at end of file