From 0aa930d1c9d97bc216f642b0f3c0d54db7c2a613 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 23 Feb 2018 11:00:03 +1000 Subject: [PATCH 01/60] manifest dashboard code --- src/Umbraco.Core/Manifest/ManifestBuilder.cs | 122 ++++++++++++++++-- src/Umbraco.Core/Manifest/ManifestParser.cs | 30 +++-- src/Umbraco.Core/Manifest/PackageManifest.cs | 12 +- .../Editors/DashboardController.cs | 4 +- src/Umbraco.Web/Editors/DashboardHelper.cs | 103 +++++++++++++-- src/Umbraco.Web/Editors/SectionController.cs | 4 +- 6 files changed, 235 insertions(+), 40 deletions(-) diff --git a/src/Umbraco.Core/Manifest/ManifestBuilder.cs b/src/Umbraco.Core/Manifest/ManifestBuilder.cs index 5f95deea22..6fc803b1f8 100644 --- a/src/Umbraco.Core/Manifest/ManifestBuilder.cs +++ b/src/Umbraco.Core/Manifest/ManifestBuilder.cs @@ -2,6 +2,8 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; +using System.Linq; +using Newtonsoft.Json; using Umbraco.Core.Cache; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; @@ -13,19 +15,20 @@ namespace Umbraco.Core.Manifest /// internal class ManifestBuilder { - private readonly IRuntimeCacheProvider _cache; + private readonly IRuntimeCacheProvider _runtimeCache; private readonly ManifestParser _parser; public ManifestBuilder(IRuntimeCacheProvider cache, ManifestParser parser) { - _cache = cache; + _runtimeCache = cache; _parser = parser; } - private const string GridEditorsKey = "grideditors"; - private const string PropertyEditorsKey = "propertyeditors"; - private const string ParameterEditorsKey = "parametereditors"; - + public const string GridEditorsKey = "gridEditors"; + public const string PropertyEditorsKey = "propertyEditors"; + public const string ParameterEditorsKey = "parameterEditors"; + public const string DashboardsKey = "dashboards"; + /// /// Returns all grid editors found in the manfifests /// @@ -33,7 +36,7 @@ namespace Umbraco.Core.Manifest { get { - return _cache.GetCacheItem>( + return _runtimeCache.GetCacheItem>( typeof (ManifestBuilder) + GridEditorsKey, () => { @@ -58,7 +61,7 @@ namespace Umbraco.Core.Manifest { get { - return _cache.GetCacheItem>( + return _runtimeCache.GetCacheItem>( typeof(ManifestBuilder) + PropertyEditorsKey, () => { @@ -83,7 +86,7 @@ namespace Umbraco.Core.Manifest { get { - return _cache.GetCacheItem>( + return _runtimeCache.GetCacheItem>( typeof (ManifestBuilder) + ParameterEditorsKey, () => { @@ -98,7 +101,104 @@ namespace Umbraco.Core.Manifest return editors; }, new TimeSpan(0, 10, 0)); } + } + + /// + /// Returns all dashboards found in the manfifests + /// + internal IDictionary Dashboards + { + get + { + //TODO: Need to integrate the security with the manifest dashboards + + return _runtimeCache.GetCacheItem>( + typeof(ManifestBuilder) + DashboardsKey, + () => + { + var dashboards = new Dictionary(); + foreach (var manifest in _parser.GetManifests()) + { + if (manifest.Dashboards != null) + { + var converted = manifest.Dashboards.ToDictionary(x => x.Key, x => x.Value.ToObject
()); + foreach (var item in converted) + { + Section existing; + if (dashboards.TryGetValue(item.Key, out existing)) + { + foreach (var area in item.Value.Areas) + { + if (existing.Areas.Contains(area, StringComparer.InvariantCultureIgnoreCase) == false) + existing.Areas.Add(area); + } + + //merge + foreach (var tab in item.Value.Tabs) + { + Tab existingTab; + if (existing.Tabs.TryGetValue(tab.Key, out existingTab)) + { + //merge + foreach (var control in tab.Value.Controls) + { + existingTab.Controls.Add(control); + } + } + else + { + existing.Tabs[tab.Key] = tab.Value; + } + } + ; + } + else + { + dashboards[item.Key] = item.Value; + } + } + } + } + return dashboards; + }, new TimeSpan(0, 10, 0)); + } + } + + #region Internal manifest models + internal class Section + { + public Section() + { + Areas = new List(); + Tabs = new Dictionary(); + } + [JsonProperty("areas")] + public List Areas { get; set; } + [JsonProperty("tabs")] + public IDictionary Tabs { get; set; } + } + + internal class Tab + { + public Tab() + { + Controls = new List(); + Index = int.MaxValue; //default so we can check if this value has been explicitly set + } + [JsonProperty("controls")] + public List Controls { get; set; } + [JsonProperty("index")] + public int Index { get; set; } + } + + internal class Control + { + [JsonProperty("path")] + public string Path { get; set; } + [JsonProperty("caption")] + public string Caption { get; set; } } - + #endregion + } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Manifest/ManifestParser.cs b/src/Umbraco.Core/Manifest/ManifestParser.cs index e30d188339..77f52bac13 100644 --- a/src/Umbraco.Core/Manifest/ManifestParser.cs +++ b/src/Umbraco.Core/Manifest/ManifestParser.cs @@ -185,26 +185,33 @@ namespace Umbraco.Core.Manifest } //validate the property editors section - var propEditors = deserialized.Properties().Where(x => x.Name == "propertyEditors").ToArray(); + var propEditors = deserialized.Properties().Where(x => x.Name == ManifestBuilder.PropertyEditorsKey).ToArray(); if (propEditors.Length > 1) { throw new FormatException("The manifest is not formatted correctly contains more than one 'propertyEditors' element"); } //validate the parameterEditors section - var paramEditors = deserialized.Properties().Where(x => x.Name == "parameterEditors").ToArray(); + var paramEditors = deserialized.Properties().Where(x => x.Name == ManifestBuilder.ParameterEditorsKey).ToArray(); if (paramEditors.Length > 1) { throw new FormatException("The manifest is not formatted correctly contains more than one 'parameterEditors' element"); } //validate the gridEditors section - var gridEditors = deserialized.Properties().Where(x => x.Name == "gridEditors").ToArray(); + var gridEditors = deserialized.Properties().Where(x => x.Name == ManifestBuilder.GridEditorsKey).ToArray(); if (gridEditors.Length > 1) { throw new FormatException("The manifest is not formatted correctly contains more than one 'gridEditors' element"); } + //validate the dashboards section + var dashboards = deserialized.Properties().Where(x => x.Name == "dashboards").ToArray(); + if (dashboards.Length > 1) + { + throw new FormatException("The manifest is not formatted correctly contains more than one 'dashboards' element"); + } + var jConfig = init.Any() ? (JArray)deserialized["javascript"] : new JArray(); ReplaceVirtualPaths(jConfig); @@ -212,9 +219,9 @@ namespace Umbraco.Core.Manifest ReplaceVirtualPaths(cssConfig); //replace virtual paths for each property editor - if (deserialized["propertyEditors"] != null) + if (deserialized[ManifestBuilder.PropertyEditorsKey] != null) { - foreach (JObject p in deserialized["propertyEditors"]) + foreach (JObject p in deserialized[ManifestBuilder.PropertyEditorsKey]) { if (p["editor"] != null) { @@ -228,9 +235,9 @@ namespace Umbraco.Core.Manifest } //replace virtual paths for each property editor - if (deserialized["gridEditors"] != null) + if (deserialized[ManifestBuilder.GridEditorsKey] != null) { - foreach (JObject p in deserialized["gridEditors"]) + foreach (JObject p in deserialized[ManifestBuilder.GridEditorsKey]) { if (p["view"] != null) { @@ -247,9 +254,10 @@ namespace Umbraco.Core.Manifest { JavaScriptInitialize = jConfig, StylesheetInitialize = cssConfig, - PropertyEditors = propEditors.Any() ? (JArray)deserialized["propertyEditors"] : new JArray(), - ParameterEditors = paramEditors.Any() ? (JArray)deserialized["parameterEditors"] : new JArray(), - GridEditors = gridEditors.Any() ? (JArray)deserialized["gridEditors"] : new JArray() + PropertyEditors = propEditors.Any() ? (JArray)deserialized[ManifestBuilder.PropertyEditorsKey] : new JArray(), + ParameterEditors = paramEditors.Any() ? (JArray)deserialized[ManifestBuilder.ParameterEditorsKey] : new JArray(), + GridEditors = gridEditors.Any() ? (JArray)deserialized[ManifestBuilder.GridEditorsKey] : new JArray(), + Dashboards = dashboards.Any() ? deserialized[ManifestBuilder.DashboardsKey].ToObject>() : new Dictionary() }; result.Add(manifest); } @@ -353,4 +361,4 @@ namespace Umbraco.Core.Manifest } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index dea1eb9877..0c37591e0b 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; namespace Umbraco.Core.Manifest { @@ -26,10 +27,15 @@ namespace Umbraco.Core.Manifest /// The json array of parameter editors /// public JArray ParameterEditors { get; set; } - + /// /// The json array of grid editors /// public JArray GridEditors { get; set; } + + /// + /// The dictionary of dashboards + /// + public IDictionary Dashboards { get; set; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 55286d99b4..efa0d50f1c 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -123,8 +123,8 @@ namespace Umbraco.Web.Editors [ValidateAngularAntiForgeryToken] public IEnumerable> GetDashboard(string section) { - var dashboardHelper = new DashboardHelper(Services.SectionService); - return dashboardHelper.GetDashboard(section, Security.CurrentUser); + var dashboardHelper = new DashboardHelper(ApplicationContext); + return dashboardHelper.GetDashboard(section, Security.CurrentUser); } } } diff --git a/src/Umbraco.Web/Editors/DashboardHelper.cs b/src/Umbraco.Web/Editors/DashboardHelper.cs index a54df7d795..a5f84b5a68 100644 --- a/src/Umbraco.Web/Editors/DashboardHelper.cs +++ b/src/Umbraco.Web/Editors/DashboardHelper.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Manifest; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; @@ -12,12 +15,12 @@ namespace Umbraco.Web.Editors { internal class DashboardHelper { - private readonly ISectionService _sectionService; + private readonly ApplicationContext _appContext; - public DashboardHelper(ISectionService sectionService) + public DashboardHelper(ApplicationContext appContext) { - if (sectionService == null) throw new ArgumentNullException("sectionService"); - _sectionService = sectionService; + if (appContext == null) throw new ArgumentNullException("appContext"); + _appContext = appContext; } /// @@ -28,7 +31,7 @@ namespace Umbraco.Web.Editors public IDictionary>> GetDashboards(IUser currentUser) { var result = new Dictionary>>(); - foreach (var section in _sectionService.GetSections()) + foreach (var section in _appContext.Services.SectionService.GetSections()) { result[section.Alias] = GetDashboard(section.Alias, currentUser); } @@ -42,29 +45,64 @@ namespace Umbraco.Web.Editors /// /// public IEnumerable> GetDashboard(string section, IUser currentUser) + { + var configDashboards = GetDashboardsFromConfig(1, section, currentUser); + var pluginDashboards = GetDashboardsFromPlugins(configDashboards.Count + 1, section, currentUser); + + //now we need to merge them, the plugin ones would replace anything matched in the config one where the tab alias matches + var added = new List>(); //to track the ones we'll add + foreach (var configDashboard in configDashboards) + { + var matched = pluginDashboards.Where(x => string.Equals(x.Alias, configDashboard.Alias, StringComparison.InvariantCultureIgnoreCase)).ToList(); + foreach (var tab in matched) + { + configDashboard.Label = tab.Label; //overwrite + configDashboard.Properties = configDashboard.Properties.Concat(tab.Properties).ToList(); //combine + added.Add(tab); //track this + } + } + + //now add the plugin dashboards to the config dashboards that have not already been added + var toAdd = pluginDashboards.Where(pluginDashboard => added.Contains(pluginDashboard) == false).ToList(); + configDashboards.AddRange(toAdd); + + //last thing is to re-sort and ID the tabs + configDashboards.Sort((tab, tab1) => tab.Id > tab1.Id ? 1 : 0); + for (var index = 0; index < configDashboards.Count; index++) + { + var tab = configDashboards[index]; + tab.Id = (index + 1); + if (tab.Id == 1) + tab.IsActive = true; + } + + return configDashboards; + } + + private List> GetDashboardsFromConfig(int startTabId, string section, IUser currentUser) { var tabs = new List>(); - var i = 1; + var i = startTabId; // The dashboard config can contain more than one area inserted by a package. foreach (var dashboardSection in UmbracoConfig.For.DashboardSettings().Sections.Where(x => x.Areas.Contains(section))) { //we need to validate access to this section - if (DashboardSecurity.AuthorizeAccess(dashboardSection, currentUser, _sectionService) == false) + if (DashboardSecurity.AuthorizeAccess(dashboardSection, currentUser, _appContext.Services.SectionService) == false) continue; //User is authorized foreach (var tab in dashboardSection.Tabs) { //we need to validate access to this tab - if (DashboardSecurity.AuthorizeAccess(tab, currentUser, _sectionService) == false) + if (DashboardSecurity.AuthorizeAccess(tab, currentUser, _appContext.Services.SectionService) == false) continue; var dashboardControls = new List(); foreach (var control in tab.Controls) { - if (DashboardSecurity.AuthorizeAccess(control, currentUser, _sectionService) == false) + if (DashboardSecurity.AuthorizeAccess(control, currentUser, _appContext.Services.SectionService) == false) continue; var dashboardControl = new DashboardControl(); @@ -81,7 +119,6 @@ namespace Umbraco.Web.Editors { Id = i, Alias = tab.Caption.ToSafeAlias(), - IsActive = i == 1, Label = tab.Caption, Properties = dashboardControls }); @@ -93,5 +130,49 @@ namespace Umbraco.Web.Editors //In case there are no tabs or a user doesn't have access the empty tabs list is returned return tabs; } + + private List> GetDashboardsFromPlugins(int startTabId, string section, IUser currentUser) + { + //TODO: Need to integrate the security with the manifest dashboards + + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var parser = new ManifestParser(appPlugins, _appContext.ApplicationCache.RuntimeCache); + var builder = new ManifestBuilder(_appContext.ApplicationCache.RuntimeCache, parser); + + var tabs = new List>(); + var i = startTabId; + + foreach (var sectionDashboard in builder.Dashboards.Where(x => x.Value.Areas.InvariantContains(section))) + { + foreach (var tab in sectionDashboard.Value.Tabs) + { + var dashboardControls = new List(); + + foreach (var control in tab.Value.Controls) + { + var dashboardControl = new DashboardControl(); + var controlPath = control.Path.Trim(); + dashboardControl.Caption = control.Caption; + dashboardControl.Path = IOHelper.FindFile(controlPath); + if (controlPath.ToLowerInvariant().EndsWith(".ascx".ToLowerInvariant())) + dashboardControl.ServerSide = true; + + dashboardControls.Add(dashboardControl); + } + + tabs.Add(new Tab + { + //assign the Id to the value of the index if one was defined, then we'll use the Id to sort later + Id = tab.Value.Index == int.MaxValue ? i : tab.Value.Index, + Alias = tab.Key.ToSafeAlias(), + Label = tab.Key, + Properties = dashboardControls + }); + + i++; + } + } + return tabs; + } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 6c94b410f9..f53cb53b52 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Editors //Check if there are empty dashboards or dashboards that will end up empty based on the current user's access //and add the meta data about them - var dashboardHelper = new DashboardHelper(Services.SectionService); + var dashboardHelper = new DashboardHelper(ApplicationContext); //this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that //since tree's by nature are controllers and require request contextual data. var appTreeController = new ApplicationTreeController @@ -72,4 +72,4 @@ namespace Umbraco.Web.Editors } } -} \ No newline at end of file +} From aa621f687eb8e019ea7773c26758f0ebef901d9b Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 13 Nov 2018 10:07:30 +0100 Subject: [PATCH 02/60] Refactor/fix registering controllers --- src/Umbraco.Core/Composing/TypeFinder.cs | 96 ++++++++++--------- src/Umbraco.Core/Composing/TypeLoader.cs | 9 ++ src/Umbraco.Web/LightInjectExtensions.cs | 93 ++++++++++++------ .../Runtime/WebRuntimeComponent.cs | 3 +- 4 files changed, 122 insertions(+), 79 deletions(-) diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index a42b84e0c5..9604f599cf 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -210,53 +210,55 @@ namespace Umbraco.Core.Composing /// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match /// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll" /// - internal static readonly string[] KnownAssemblyExclusionFilter = new[] - { - "mscorlib,", - "System.", - "Antlr3.", - "Autofac.", - "Autofac,", - "Castle.", - "ClientDependency.", - "DataAnnotationsExtensions.", - "DataAnnotationsExtensions,", - "Dynamic,", - "HtmlDiff,", - "Iesi.Collections,", - "Microsoft.", - "Newtonsoft.", - "NHibernate.", - "NHibernate,", - "NuGet.", - "RouteDebugger,", - "SqlCE4Umbraco,", - "umbraco.datalayer,", - "umbraco.interfaces,", - //"umbraco.providers,", - //"Umbraco.Web.UI,", - "umbraco.webservices", - "Lucene.", - "Examine,", - "Examine.", - "ServiceStack.", - "MySql.", - "HtmlAgilityPack.", - "TidyNet.", - "ICSharpCode.", - "CookComputing.", - "AutoMapper,", - "AutoMapper.", - "AzureDirectory,", - "itextsharp,", - "UrlRewritingNet.", - "HtmlAgilityPack,", - "MiniProfiler,", - "Moq,", - "nunit.framework,", - "TidyNet,", - "WebDriver," - }; + internal static readonly string[] KnownAssemblyExclusionFilter = { + "Antlr3.", + "AutoMapper,", + "AutoMapper.", + "Autofac,", // DI + "Autofac.", + "AzureDirectory,", + "Castle.", // DI, tests + "ClientDependency.", + "CookComputing.", + "CSharpTest.", // BTree for NuCache + "DataAnnotationsExtensions,", + "DataAnnotationsExtensions.", + "Dynamic,", + "Examine,", + "Examine.", + "HtmlAgilityPack,", + "HtmlAgilityPack.", + "HtmlDiff,", + "ICSharpCode.", + "Iesi.Collections,", // used by NHibernate + "LightInject.", // DI + "LightInject,", + "Lucene.", + "Markdown,", + "Microsoft.", + "MiniProfiler,", + "Moq,", + "MySql.", + "NHibernate,", + "NHibernate.", + "Newtonsoft.", + "NPoco,", + "NuGet.", + "RouteDebugger,", + "Semver.", + "Serilog.", + "Serilog,", + "ServiceStack.", + "SqlCE4Umbraco,", + "Superpower,", // used by Serilog + "System.", + "TidyNet,", + "TidyNet.", + "WebDriver,", + "itextsharp,", + "mscorlib,", + "nunit.framework,", + }; /// /// Finds any classes derived from the type T that contain the attribute TAttribute diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 304638e017..f79c288e91 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -520,6 +520,8 @@ namespace Umbraco.Core.Composing // if not caching, or not IDiscoverable, directly get types if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false) { + _logger.Logger.Debug("Running a full, non-cached, scan for type {TypeName} (slow).", typeof(T).FullName); + return GetTypesInternal( typeof (T), null, () => TypeFinder.FindClassesOfType(specificAssemblies ?? AssembliesToScan), @@ -559,6 +561,8 @@ namespace Umbraco.Core.Composing // if not caching, or not IDiscoverable, directly get types if (cache == false || typeof(IDiscoverable).IsAssignableFrom(typeof(T)) == false) { + _logger.Logger.Debug("Running a full, non-cached, scan for type {TypeName} / attribute {AttributeName} (slow).", typeof(T).FullName, typeof(TAttribute).FullName); + return GetTypesInternal( typeof (T), typeof (TAttribute), () => TypeFinder.FindClassesOfTypeWithAttribute(specificAssemblies ?? AssembliesToScan), @@ -595,6 +599,11 @@ namespace Umbraco.Core.Composing // do not cache anything from specific assemblies cache &= specificAssemblies == null; + if (cache == false) + { + _logger.Logger.Debug("Running a full, non-cached, scan for types / attribute {AttributeName} (slow).", typeof(TAttribute).FullName); + } + return GetTypesInternal( typeof (object), typeof (TAttribute), () => TypeFinder.FindClassesWithAttribute(specificAssemblies ?? AssembliesToScan), diff --git a/src/Umbraco.Web/LightInjectExtensions.cs b/src/Umbraco.Web/LightInjectExtensions.cs index 580dc4117d..7ea55587e0 100644 --- a/src/Umbraco.Web/LightInjectExtensions.cs +++ b/src/Umbraco.Web/LightInjectExtensions.cs @@ -1,49 +1,82 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using System.Web.Http.Controllers; using System.Web.Mvc; using LightInject; -using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi; namespace Umbraco.Web { internal static class LightInjectExtensions { /// - /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly + /// Registers Umbraco controllers. /// - /// - /// - /// - public static void RegisterMvcControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + public static void RegisterUmbracoControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly umbracoWebAssembly) { - //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again - // for all controllers? Seems like we should just do this once and then filter. That said here we are - // only scanning our own single assembly. Hrm. + // notes + // + // We scan and auto-registers: + // - every IController and IHttpController that *we* have in Umbraco.Web + // - PluginController and UmbracoApiController in every assembly + // + // We do NOT scan: + // - any IController or IHttpController (anything not PluginController nor UmbracoApiController), outside of Umbraco.Web + // which means that users HAVE to explicitly register their own non-Umbraco controllers + // + // This is because we try to achieve a balance between "simple" and "fast. Scanning for PluginController or + // UmbracoApiController is fast-ish because they both are IDiscoverable. Scanning for IController or IHttpController + // is a full, non-cached scan = expensive, we do it only for 1 assembly. + // + // TODO + // find a way to scan for IController *and* IHttpController in one single pass + // or, actually register them manually so don't require a full scan for these + // 5 are IController but not PluginController + // Umbraco.Web.Mvc.RenderMvcController + // Umbraco.Web.Install.Controllers.InstallController + // Umbraco.Web.Macros.PartialViewMacroController + // Umbraco.Web.Editors.PreviewController + // Umbraco.Web.Editors.BackOfficeController + // 9 are IHttpController but not UmbracoApiController + // Umbraco.Web.Controllers.UmbProfileController + // Umbraco.Web.Controllers.UmbLoginStatusController + // Umbraco.Web.Controllers.UmbRegisterController + // Umbraco.Web.Controllers.UmbLoginController + // Umbraco.Web.Mvc.RenderMvcController + // Umbraco.Web.Install.Controllers.InstallController + // Umbraco.Web.Macros.PartialViewMacroController + // Umbraco.Web.Editors.PreviewController + // Umbraco.Web.Editors.BackOfficeController - container.RegisterControllers(typeLoader, assembly); + // scan and register every IController in Umbraco.Web + var umbracoWebControllers = typeLoader.GetTypes(specificAssemblies: new[] { umbracoWebAssembly }); + //foreach (var controller in umbracoWebControllers.Where(x => !typeof(PluginController).IsAssignableFrom(x))) + // Current.Logger.Debug(typeof(LightInjectExtensions), "IController NOT PluginController: " + controller.FullName); + container.RegisterControllers(umbracoWebControllers); + + // scan and register every PluginController in everything (PluginController is IDiscoverable and IController) + var nonUmbracoWebPluginController = typeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); + container.RegisterControllers(nonUmbracoWebPluginController); + + // scan and register every IHttpController in Umbraco.Web + var umbracoWebHttpControllers = typeLoader.GetTypes(specificAssemblies: new[] { umbracoWebAssembly }); + //foreach (var controller in umbracoWebControllers.Where(x => !typeof(UmbracoApiController).IsAssignableFrom(x))) + // Current.Logger.Debug(typeof(LightInjectExtensions), "IHttpController NOT UmbracoApiController: " + controller.FullName); + container.RegisterControllers(umbracoWebHttpControllers); + + // scan and register every UmbracoApiController in everything (UmbracoApiController is IDiscoverable and IHttpController) + var nonUmbracoWebApiControllers = typeLoader.GetTypes().Where(x => x.Assembly != umbracoWebAssembly); + container.RegisterControllers(nonUmbracoWebApiControllers); } - /// - /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly - /// - /// - /// - /// - public static void RegisterApiControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + private static void RegisterControllers(this IServiceRegistry container, IEnumerable controllerTypes) { - //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again - // for all controllers? Seems like we should just do this once and then filter. That said here we are - // only scanning our own single assembly. Hrm. - - container.RegisterControllers(typeLoader, assembly); - } - - private static void RegisterControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) - { - var types = typeLoader.GetTypes(specificAssemblies: new[] { assembly }); - foreach (var type in types) - container.Register(type, new PerRequestLifeTime()); + foreach (var controllerType in controllerTypes) + container.Register(controllerType, new PerRequestLifeTime()); } } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 1af24db636..bd09cbe918 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -122,9 +122,8 @@ namespace Umbraco.Web.Runtime composition.Container.EnableMvc(); // does container.EnablePerWebRequestScope() composition.Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) - composition.Container.RegisterMvcControllers(typeLoader, GetType().Assembly); + composition.Container.RegisterUmbracoControllers(typeLoader, GetType().Assembly); composition.Container.EnableWebApi(GlobalConfiguration.Configuration); - composition.Container.RegisterApiControllers(typeLoader, GetType().Assembly); composition.Container.RegisterCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! From e84cbc7e19a053556c5730de2402db607092f0f6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 16 Nov 2018 14:07:41 +0100 Subject: [PATCH 03/60] wip swap out bootstrap datepicker for flatpickr --- .../datepicker/datepicker.controller.js | 233 ++++++++---------- .../datepicker/datepicker.html | 42 +++- 2 files changed, 130 insertions(+), 145 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js index 9bed59b0d7..e673b17a73 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js @@ -1,38 +1,84 @@ function dateTimePickerController($scope, notificationsService, assetsService, angularHelper, userService, $element, dateHelper) { - //setup the default config - var config = { - pickDate: true, - pickTime: true, - useSeconds: true, - format: "YYYY-MM-DD HH:mm:ss", - icons: { - time: "icon-time", - date: "icon-calendar", - up: "icon-chevron-up", - down: "icon-chevron-down" - } + let flatPickr = null; - }; + function onInit() { + + $scope.hasDatetimePickerValue = $scope.model.value ? true : false; + $scope.model.datetimePickerValue = null; + $scope.serverTime = null; + $scope.serverTimeNeedsOffsetting = false; + + // setup the default config + var config = { + pickDate: true, + pickTime: true, + useSeconds: true, + format: "YYYY-MM-DD HH:mm:ss", + icons: { + time: "icon-time", + date: "icon-calendar", + up: "icon-chevron-up", + down: "icon-chevron-down" + } + }; + + // map the user config + $scope.model.config = angular.extend(config, $scope.model.config); + + // ensure the format doesn't get overwritten with an empty string + if ($scope.model.config.format === "" || $scope.model.config.format === undefined || $scope.model.config.format === null) { + $scope.model.config.format = $scope.model.config.pickTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD"; + } + + // check whether a server time offset is needed + if (Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) { + // Will return something like 120 + var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset; + + // Will return something like -120 + var localOffset = new Date().getTimezoneOffset(); + + // If these aren't equal then offsetting is needed + // note the minus in front of serverOffset needed + // because C# and javascript return the inverse offset + $scope.serverTimeNeedsOffsetting = (-serverOffset !== localOffset); + } + + //get the current user to see if we can localize this picker + userService.getCurrentUser().then(function (user) { + + const dateFormat = $scope.model.config.pickTime ? "Y-m-d H:i:S" : "Y-m-d"; + + // date picker config + $scope.datePickerConfig = { + enableTime: $scope.model.config.pickTime, + dateFormat: dateFormat, + time_24hr: true + }; + + $scope.model.config.language = user.locale; + + setDatePickerVal(); + + }); - //map the user config - $scope.model.config = angular.extend(config, $scope.model.config); - //ensure the format doesn't get overwritten with an empty string - if ($scope.model.config.format === "" || $scope.model.config.format === undefined || $scope.model.config.format === null) { - $scope.model.config.format = $scope.model.config.pickTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD"; } - $scope.hasDatetimePickerValue = $scope.model.value ? true : false; - $scope.datetimePickerValue = null; + $scope.clearDate = function() { + $scope.hasDatetimePickerValue = false; + $scope.model.datetimePickerValue = null; + $scope.model.value = null; + $scope.datePickerForm.datepicker.$setValidity("pickerError", true); + } - //hide picker if clicking on the document - $scope.hidePicker = function () { - //$element.find("div:first").datetimepicker("hide"); - // Sometimes the statement above fails and generates errors in the browser console. The following statements fix that. - var dtp = $element.find("div:first"); - if (dtp && dtp.datetimepicker) { - dtp.datetimepicker("hide"); - } + $scope.datePickerSetup = function(instance) { + flatPickr = instance; + }; + + $scope.datePickerChange = function(date) { + setDate(date); + setDatePickerVal(); }; //here we declare a special method which will be called whenever the value has changed from the server @@ -44,53 +90,45 @@ function dateTimePickerController($scope, notificationsService, assetsService, a var newDate = moment(newVal); if (newDate.isAfter(minDate)) { - applyDate({ date: moment(newVal) }); + setDate(newVal); } else { $scope.clearDate(); } } }; - - //handles the date changing via the date picker - function applyDate(e) { + + function setDate(date) { + const momentDate = moment(date); angularHelper.safeApply($scope, function() { // when a date is changed, update the model - if (e.date && e.date.isValid()) { + if (momentDate && momentDate.isValid()) { $scope.datePickerForm.datepicker.$setValidity("pickerError", true); $scope.hasDatetimePickerValue = true; - $scope.datetimePickerValue = e.date.format($scope.model.config.format); + $scope.model.datetimePickerValue = momentDate.format($scope.model.config.format); } else { $scope.hasDatetimePickerValue = false; - $scope.datetimePickerValue = null; - } - - setModelValue(); - - if (!$scope.model.config.pickTime) { - $element.find("div:first").datetimepicker("hide", 0); + $scope.model.datetimePickerValue = null; } + updateModelValue(date); }); } - //sets the scope model value accordingly - this is the value to be sent up to the server and depends on - // if the picker is configured to offset time. We always format the date/time in a specific format for sending - // to the server, this is different from the format used to display the date/time. - function setModelValue() { + function updateModelValue(date) { + const momentDate = moment(date); if ($scope.hasDatetimePickerValue) { - var elementData = $element.find("div:first").data().DateTimePicker; if ($scope.model.config.pickTime) { //check if we are supposed to offset the time if ($scope.model.value && Object.toBoolean($scope.model.config.offsetTime) && Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) { - $scope.model.value = dateHelper.convertToServerStringTime(elementData.getDate(), Umbraco.Sys.ServerVariables.application.serverTimeOffset); - $scope.serverTime = dateHelper.convertToServerStringTime(elementData.getDate(), Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z"); + $scope.model.value = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset); + $scope.serverTime = dateHelper.convertToServerStringTime(momentDate, Umbraco.Sys.ServerVariables.application.serverTimeOffset, "YYYY-MM-DD HH:mm:ss Z"); } else { - $scope.model.value = elementData.getDate().format("YYYY-MM-DD HH:mm:ss"); + $scope.model.value = momentDate.format("YYYY-MM-DD HH:mm:ss"); } } else { - $scope.model.value = elementData.getDate().format("YYYY-MM-DD"); + $scope.model.value = momentDate.format("YYYY-MM-DD"); } } else { @@ -99,7 +137,7 @@ function dateTimePickerController($scope, notificationsService, assetsService, a } /** Sets the value of the date picker control adn associated viewModel objects based on the model value */ - function setDatePickerVal(element) { + function setDatePickerVal() { if ($scope.model.value) { var dateVal; //check if we are supposed to offset the time @@ -112,98 +150,21 @@ function dateTimePickerController($scope, notificationsService, assetsService, a //create a normal moment , no offset required var dateVal = $scope.model.value ? moment($scope.model.value, "YYYY-MM-DD HH:mm:ss") : moment(); } - - element.datetimepicker("setValue", dateVal); - $scope.datetimePickerValue = dateVal.format($scope.model.config.format); + $scope.model.datetimePickerValue = dateVal.format($scope.model.config.format); } else { $scope.clearDate(); } } - $scope.clearDate = function() { - $scope.hasDatetimePickerValue = false; - $scope.datetimePickerValue = null; - $scope.model.value = null; - $scope.datePickerForm.datepicker.$setValidity("pickerError", true); - } - - $scope.serverTime = null; - $scope.serverTimeNeedsOffsetting = false; - if (Umbraco.Sys.ServerVariables.application.serverTimeOffset !== undefined) { - // Will return something like 120 - var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset; - - // Will return something like -120 - var localOffset = new Date().getTimezoneOffset(); - - // If these aren't equal then offsetting is needed - // note the minus in front of serverOffset needed - // because C# and javascript return the inverse offset - $scope.serverTimeNeedsOffsetting = (-serverOffset !== localOffset); - } - - //get the current user to see if we can localize this picker - userService.getCurrentUser().then(function (user) { - - assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css', $scope).then(function() { - - var filesToLoad = ["lib/datetimepicker/bootstrap-datetimepicker.js"]; - - - $scope.model.config.language = user.locale; - - - assetsService.load(filesToLoad, $scope).then( - function () { - //The Datepicker js and css files are available and all components are ready to use. - - // Get the id of the datepicker button that was clicked - var pickerId = $scope.model.alias; - - var element = $element.find("div:first"); - - // Create the datepicker and add a changeDate eventlistener - element - .datetimepicker(angular.extend({ useCurrent: true }, $scope.model.config)) - .on("dp.change", applyDate) - .on("dp.error", function(a, b, c) { - $scope.hasDatetimePickerValue = false; - $scope.datePickerForm.datepicker.$setValidity("pickerError", false); - }); - - $(document).bind("click", $scope.hidePicker); - - setDatePickerVal(element); - - element.find("input").bind("blur", function() { - //we need to force an apply here - $scope.$apply(); - }); - - $scope.$watch("model.value", function(newVal, oldVal) { - if (newVal !== oldVal) { - $scope.hasDatetimePickerValue = newVal ? true : false; - setDatePickerVal(element); - } - }); - - var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { - setModelValue(); - }); - - //Ensure to remove the event handler when this instance is destroyted - $scope.$on('$destroy', function () { - element.find("input").unbind("blur"); - element.datetimepicker("destroy"); - unsubscribe(); - $(document).unbind("click", $scope.hidePicker); - }); - - }); - }); - + $scope.$watch("model.value", function(newVal, oldVal) { + if (newVal !== oldVal) { + $scope.hasDatetimePickerValue = newVal ? true : false; + setDatePickerVal(); + } }); + + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index 258d2040d5..f9b5271e0a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -1,17 +1,30 @@
-
- +
- - - + + +
+ + + + +
+ +
@@ -29,5 +42,16 @@ Clear date

+
+
+
model.value
+ {{model.value}} +
+
+
Date time picker value
+ {{model.datetimePickerValue}} +
+
+
From 24913128d1507b37393e4387a54f8acd2823f295 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 12:42:27 +0100 Subject: [PATCH 04/60] add option to show a caret in a umb-button --- .../directives/components/buttons/umbbutton.directive.js | 4 +++- .../src/less/components/buttons/umb-button.less | 5 +++++ .../src/views/components/buttons/umb-button.html | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index 1d52c4e451..923cac80f5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -66,6 +66,7 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {string=} size Set a button icon ("xs", "m", "l", "xl"). @param {boolean=} disabled Set to true to disable the button. @param {string=} addEllipsis Adds an ellipsis character (…) to the button label which means the button will open a dialog or prompt the user for more information. +@param {string=} showCaret Shows a caret on the right side of the button label **/ @@ -93,7 +94,8 @@ Use this directive to render an umbraco button. The directive can be used to gen disabled: " {{vm.buttonLabel}} + @@ -18,6 +19,7 @@ {{vm.buttonLabel}} + @@ -25,6 +27,7 @@ {{vm.buttonLabel}} + From 5e4770fd8c4d081c539e2f3185e8bddd2e3157d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 12:47:30 +0100 Subject: [PATCH 05/60] use umbraco components instead of bootstrap for button groups --- .../buttons/umbbuttongroup.directive.js | 64 +++++++++++++------ .../components/buttons/umb-button-group.html | 15 +++-- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttongroup.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttongroup.directive.js index bce81c1ffd..74f0870f1b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttongroup.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttongroup.directive.js @@ -89,30 +89,52 @@ Use this directive to render a button with a dropdown of alternative actions. @param {string=} float Set the float of the dropdown. ("left", "right"). **/ -(function() { - 'use strict'; +(function () { + 'use strict'; - function ButtonGroupDirective() { + function ButtonGroupDirective() { - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/buttons/umb-button-group.html', - scope: { - defaultButton: "=", - subButtons: "=", - state: "=?", - direction: "@?", - float: "@?", - buttonStyle: "@?", - size: "@?", - icon: "@?" - } - }; + function link(scope) { - return directive; - } + scope.dropdown = { + isOpen: false + }; - angular.module('umbraco.directives').directive('umbButtonGroup', ButtonGroupDirective); + scope.toggleDropdown = function() { + scope.dropdown.isOpen = !scope.dropdown.isOpen; + }; + + scope.closeDropdown = function() { + scope.dropdown.isOpen = false; + }; + + scope.executeMenuItem = function(subButton) { + subButton.handler(); + scope.closeDropdown(); + }; + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/buttons/umb-button-group.html', + scope: { + defaultButton: "=", + subButtons: "=", + state: "=?", + direction: "@?", + float: "@?", + buttonStyle: "@?", + size: "@?", + icon: "@?" + }, + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbButtonGroup', ButtonGroupDirective); })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html index 3810630fa9..054681d7f1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html @@ -16,17 +16,20 @@ add-ellipsis={{defaultButton.addEllipsis}}> - + - + +
From 138895d5e76f18112181b929feb268b5153e3a74 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 12:48:31 +0100 Subject: [PATCH 06/60] use umb dropdown component for actions menu --- .../editor/umbeditormenu.directive.js | 87 +++++++++++-------- .../components/editor/umb-editor-menu.html | 28 +++--- 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js index b6af7a4ca6..22939c7f2c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js @@ -1,50 +1,63 @@ -(function() { - 'use strict'; +(function () { + 'use strict'; - function EditorMenuDirective($injector, treeService, navigationService, umbModelMapper, appState) { + function EditorMenuDirective($injector, treeService, navigationService, umbModelMapper, appState) { - function link(scope, el, attr, ctrl) { + function link(scope, el, attr, ctrl) { - //adds a handler to the context menu item click, we need to handle this differently - //depending on what the menu item is supposed to do. - scope.executeMenuItem = function (action) { - navigationService.executeMenuAction(action, scope.currentNode, scope.currentSection); - }; + scope.dropdown = { + isOpen: false + }; - //callback method to go and get the options async - scope.getOptions = function () { + function onInit() { - if (!scope.currentNode) { - return; - } + getOptions(); - //when the options item is selected, we need to set the current menu item in appState (since this is synonymous with a menu) - appState.setMenuState("currentNode", scope.currentNode); + } - if (!scope.actions) { - treeService.getMenu({ treeNode: scope.currentNode }) - .then(function (data) { - scope.actions = data.menuItems; - }); - } - }; + //adds a handler to the context menu item click, we need to handle this differently + //depending on what the menu item is supposed to do. + scope.executeMenuItem = function (action) { + navigationService.executeMenuAction(action, scope.currentNode, scope.currentSection); + scope.dropdown.isOpen = false; + }; - } + //callback method to go and get the options async + function getOptions() { - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/editor/umb-editor-menu.html', - link: link, - scope: { - currentNode: "=", - currentSection: "@" - } - }; + if (!scope.currentNode) { + return; + } - return directive; - } + //when the options item is selected, we need to set the current menu item in appState (since this is synonymous with a menu) + appState.setMenuState("currentNode", scope.currentNode); - angular.module('umbraco.directives').directive('umbEditorMenu', EditorMenuDirective); + if (!scope.actions) { + treeService.getMenu({ treeNode: scope.currentNode }) + .then(function (data) { + scope.actions = data.menuItems; + }); + } + }; + + onInit(); + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/editor/umb-editor-menu.html', + link: link, + scope: { + currentNode: "=", + currentSection: "@" + } + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbEditorMenu', EditorMenuDirective); })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html index bf9c8fab8c..032e4cd6c3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html @@ -1,22 +1,20 @@
- - - Actions - - + + - - + + +
From 477a9bae0e842f593288e3c4417c510369e31bc4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 13:15:28 +0100 Subject: [PATCH 07/60] use umb dropdown instead of boostrap dropdown in permissions context menu --- .../content/content.rights.controller.js | 2 ++ .../src/views/content/rights.html | 22 +++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js index afab478fc4..a8f87ce2c9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js @@ -63,6 +63,8 @@ vm.labels.permissionsSetForGroup = value; }); setViewSate("managePermissions"); + // hide dropdown + vm.groupsDropdownOpen = false; } function assignGroupPermissions(group) { diff --git a/src/Umbraco.Web.UI.Client/src/views/content/rights.html b/src/Umbraco.Web.UI.Client/src/views/content/rights.html index afa932e606..35f3d34260 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/rights.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/rights.html @@ -27,20 +27,24 @@

From d6bd5e7e85f0c74eb254b162fe860eb29bf71ed3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 14:14:37 +0100 Subject: [PATCH 08/60] change query builder dropdowns to umb dropdowns --- .../less/components/buttons/umb-button.less | 2 +- .../querybuilder/querybuilder.html | 150 ++++++++++-------- 2 files changed, 89 insertions(+), 63 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less index fad6c03c96..7c45801f43 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less @@ -31,7 +31,7 @@ .umb-button .umb-button__caret { margin-top: 0; - margin-left: 3px; + margin-left: 5px; } .umb-button__progress { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html index e7f0cd9a1b..6c42a05cc0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html @@ -23,26 +23,36 @@ I want from - - - {{vm.query.source.name}} - - + + +
@@ -56,52 +66,62 @@ - - + + - + - - @@ -112,30 +132,38 @@ - @@ -148,9 +176,7 @@ -
-				{{model.result.queryExpression}}
-						
+
{{model.result.queryExpression}}
From 301cc00e10f3bf9844ab598028cb722f4d85617d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 14:29:35 +0100 Subject: [PATCH 09/60] use flatpickr in query builder --- .../querybuilder/querybuilder.controller.js | 11 +++++------ .../infiniteeditors/querybuilder/querybuilder.html | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.controller.js index 1beac99928..faca3b3fa0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.controller.js @@ -15,9 +15,7 @@ vm.conditions = []; vm.datePickerConfig = { - pickDate: true, - pickTime: false, - format: "YYYY-MM-DD" + dateFormat: "Y-m-d" }; vm.chooseSource = chooseSource; @@ -180,9 +178,10 @@ throttledFunc(); } - function datePickerChange(event, filter) { - if (event.date && event.date.isValid()) { - filter.constraintValue = event.date.format(vm.datePickerConfig.format); + function datePickerChange(date, filter) { + const momentDate = moment(date); + if (momentDate && momentDate.isValid()) { + filter.constraintValue = momentDate.format(vm.datePickerConfig.format); throttledFunc(); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html index 6c42a05cc0..4b6c6cc179 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html @@ -114,10 +114,10 @@ - - + + From 0f07e6830d58dfe03c30749485cde95a43ecdeff Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 14:56:27 +0100 Subject: [PATCH 10/60] delete bootstrap datepicker files --- .../bootstrap-datetimepicker.js | 1436 ----------------- .../bootstrap-datetimepicker.min.css | 5 - .../components/umbdatetimepicker.directive.js | 186 --- 3 files changed, 1627 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.min.css delete mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js diff --git a/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.js b/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.js deleted file mode 100644 index 1ec2e9374d..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.js +++ /dev/null @@ -1,1436 +0,0 @@ -/* -//! version : 3.1.3 -========================================================= -bootstrap-datetimepicker.js -https://github.com/Eonasdan/bootstrap-datetimepicker -========================================================= -The MIT License (MIT) - -Copyright (c) 2014 Jonathan Peterson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -;(function (root, factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // AMD is used - Register as an anonymous module. - define(['jquery', 'moment'], factory); - } else if (typeof exports === 'object') { - factory(require('jquery'), require('moment')); - } - else { - // Neither AMD or CommonJS used. Use global variables. - if (!jQuery) { - throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first'); - } - if (!moment) { - throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first'); - } - factory(root.jQuery, moment); - } -}(this, function ($, moment) { - 'use strict'; - if (typeof moment === 'undefined') { - throw new Error('momentjs is required'); - } - - var dpgId = 0, - - DateTimePicker = function (element, options) { - var defaults = $.fn.datetimepicker.defaults, - - icons = { - time: 'glyphicon glyphicon-time', - date: 'glyphicon glyphicon-calendar', - up: 'glyphicon glyphicon-chevron-up', - down: 'glyphicon glyphicon-chevron-down' - }, - - picker = this, - errored = false, - dDate, - - init = function () { - var icon = false, localeData, rInterval; - picker.options = $.extend({}, defaults, options); - picker.options.icons = $.extend({}, icons, picker.options.icons); - - picker.element = $(element); - - dataToOptions(); - - if (!(picker.options.pickTime || picker.options.pickDate)) { - throw new Error('Must choose at least one picker'); - } - - picker.id = dpgId++; - moment.locale(picker.options.language); - picker.date = moment(); - picker.unset = false; - picker.isInput = picker.element.is('input'); - picker.component = false; - - if (picker.element.hasClass('input-group')) { - if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48 - picker.component = picker.element.find('[class^="input-group-"]'); - } - else { - picker.component = picker.element.find('.datepickerbutton'); - } - } - picker.format = picker.options.format; - - localeData = moment().localeData(); - - if (!picker.format) { - picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : ''); - if (picker.options.pickDate && picker.options.pickTime) { - picker.format += ' '; - } - picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : ''); - if (picker.options.useSeconds) { - if (localeData.longDateFormat('LT').indexOf(' A') !== -1) { - picker.format = picker.format.split(' A')[0] + ':ss A'; - } - else { - picker.format += ':ss'; - } - } - } - picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0); - - if (picker.component) { - icon = picker.component.find('span'); - } - - if (picker.options.pickTime) { - if (icon) { - icon.addClass(picker.options.icons.time); - } - } - if (picker.options.pickDate) { - if (icon) { - icon.removeClass(picker.options.icons.time); - icon.addClass(picker.options.icons.date); - } - } - - picker.options.widgetParent = - typeof picker.options.widgetParent === 'string' && picker.options.widgetParent || - picker.element.parents().filter(function () { - return 'scroll' === $(this).css('overflow-y'); - }).get(0) || - 'body'; - - picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent); - - picker.minViewMode = picker.options.minViewMode || 0; - if (typeof picker.minViewMode === 'string') { - switch (picker.minViewMode) { - case 'months': - picker.minViewMode = 1; - break; - case 'years': - picker.minViewMode = 2; - break; - default: - picker.minViewMode = 0; - break; - } - } - picker.viewMode = picker.options.viewMode || 0; - if (typeof picker.viewMode === 'string') { - switch (picker.viewMode) { - case 'months': - picker.viewMode = 1; - break; - case 'years': - picker.viewMode = 2; - break; - default: - picker.viewMode = 0; - break; - } - } - - picker.viewMode = Math.max(picker.viewMode, picker.minViewMode); - - picker.options.disabledDates = indexGivenDates(picker.options.disabledDates); - picker.options.enabledDates = indexGivenDates(picker.options.enabledDates); - - picker.startViewMode = picker.viewMode; - picker.setMinDate(picker.options.minDate); - picker.setMaxDate(picker.options.maxDate); - fillDow(); - fillMonths(); - fillHours(); - fillMinutes(); - fillSeconds(); - update(); - showMode(); - if (!getPickerInput().prop('disabled')) { - attachDatePickerEvents(); - } - if (picker.options.defaultDate !== '' && getPickerInput().val() === '') { - picker.setValue(picker.options.defaultDate); - } - if (picker.options.minuteStepping !== 1) { - rInterval = picker.options.minuteStepping; - picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0); - } - }, - - getPickerInput = function () { - var input; - - if (picker.isInput) { - return picker.element; - } - input = picker.element.find('.datepickerinput'); - if (input.size() === 0) { - input = picker.element.find('input'); - } - else if (!input.is('input')) { - throw new Error('CSS class "datepickerinput" cannot be applied to non input element'); - } - return input; - }, - - dataToOptions = function () { - var eData; - if (picker.element.is('input')) { - eData = picker.element.data(); - } - else { - eData = picker.element.find('input').data(); - } - if (eData.dateFormat !== undefined) { - picker.options.format = eData.dateFormat; - } - if (eData.datePickdate !== undefined) { - picker.options.pickDate = eData.datePickdate; - } - if (eData.datePicktime !== undefined) { - picker.options.pickTime = eData.datePicktime; - } - if (eData.dateUseminutes !== undefined) { - picker.options.useMinutes = eData.dateUseminutes; - } - if (eData.dateUseseconds !== undefined) { - picker.options.useSeconds = eData.dateUseseconds; - } - if (eData.dateUsecurrent !== undefined) { - picker.options.useCurrent = eData.dateUsecurrent; - } - if (eData.calendarWeeks !== undefined) { - picker.options.calendarWeeks = eData.calendarWeeks; - } - if (eData.dateMinutestepping !== undefined) { - picker.options.minuteStepping = eData.dateMinutestepping; - } - if (eData.dateMindate !== undefined) { - picker.options.minDate = eData.dateMindate; - } - if (eData.dateMaxdate !== undefined) { - picker.options.maxDate = eData.dateMaxdate; - } - if (eData.dateShowtoday !== undefined) { - picker.options.showToday = eData.dateShowtoday; - } - if (eData.dateCollapse !== undefined) { - picker.options.collapse = eData.dateCollapse; - } - if (eData.dateLanguage !== undefined) { - picker.options.language = eData.dateLanguage; - } - if (eData.dateDefaultdate !== undefined) { - picker.options.defaultDate = eData.dateDefaultdate; - } - if (eData.dateDisableddates !== undefined) { - picker.options.disabledDates = eData.dateDisableddates; - } - if (eData.dateEnableddates !== undefined) { - picker.options.enabledDates = eData.dateEnableddates; - } - if (eData.dateIcons !== undefined) { - picker.options.icons = eData.dateIcons; - } - if (eData.dateUsestrict !== undefined) { - picker.options.useStrict = eData.dateUsestrict; - } - if (eData.dateDirection !== undefined) { - picker.options.direction = eData.dateDirection; - } - if (eData.dateSidebyside !== undefined) { - picker.options.sideBySide = eData.dateSidebyside; - } - if (eData.dateDaysofweekdisabled !== undefined) { - picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled; - } - }, - - place = function () { - var position = 'absolute', - offset = picker.component ? picker.component.offset() : picker.element.offset(), - $window = $(window), - placePosition; - - picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth(); - offset.top = offset.top + picker.element.outerHeight(); - - if (picker.options.direction === 'up') { - placePosition = 'top'; - } else if (picker.options.direction === 'bottom') { - placePosition = 'bottom'; - } else if (picker.options.direction === 'auto') { - if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) { - placePosition = 'top'; - } else { - placePosition = 'bottom'; - } - } - if (placePosition === 'top') { - offset.bottom = $window.height() - offset.top + picker.element.outerHeight() + 3; - picker.widget.addClass('top').removeClass('bottom'); - } else { - offset.top += 1; - picker.widget.addClass('bottom').removeClass('top'); - } - - if (picker.options.width !== undefined) { - picker.widget.width(picker.options.width); - } - - if (picker.options.orientation === 'left') { - picker.widget.addClass('left-oriented'); - offset.left = offset.left - picker.widget.width() + 20; - } - - if (isInFixed()) { - position = 'fixed'; - offset.top -= $window.scrollTop(); - offset.left -= $window.scrollLeft(); - } - - if ($window.width() < offset.left + picker.widget.outerWidth()) { - offset.right = $window.width() - offset.left - picker.width; - offset.left = 'auto'; - picker.widget.addClass('pull-right'); - } else { - offset.right = 'auto'; - picker.widget.removeClass('pull-right'); - } - - if (placePosition === 'top') { - picker.widget.css({ - position: position, - bottom: offset.bottom, - top: 'auto', - left: offset.left, - right: offset.right - }); - } else { - picker.widget.css({ - position: position, - top: offset.top, - bottom: 'auto', - left: offset.left, - right: offset.right - }); - } - }, - - notifyChange = function (oldDate, eventType) { - if (moment(picker.date).isSame(moment(oldDate)) && !errored) { - return; - } - errored = false; - picker.element.trigger({ - type: 'dp.change', - date: moment(picker.date), - oldDate: moment(oldDate) - }); - - if (eventType !== 'change') { - picker.element.change(); - } - - ////////MODIFICATION FOR COMPATIBILITY WITH OLD DATEPICKER - //The old datepicker doesn't handle timezones occrectly. - //This forces the new datepicker to mimick the incorrect values from the old datepicker - //To do this it formats the datetime to a string *without* timezone info and then parses that as UTC (even though it is not), then adds the timezone afterwards. - picker.element.trigger({ - type: 'changeDate', - date: moment.utc(picker.date.format("YYYY-MM-DD HH:mm:ss")).local().toDate(), - localDate: moment(picker.date).toDate() - }); - ///////END MODIFICATION FOR COMPATIBILTIY - }, - - notifyError = function (date) { - errored = true; - picker.element.trigger({ - type: 'dp.error', - date: moment(date, picker.format, picker.options.useStrict) - }); - }, - - update = function (newDate) { - moment.locale(picker.options.language); - var dateStr = newDate; - if (!dateStr) { - dateStr = getPickerInput().val(); - if (dateStr) { - picker.date = moment(dateStr, picker.format, picker.options.useStrict); - } - if (!picker.date) { - picker.date = moment(); - } - } - picker.viewDate = moment(picker.date).startOf('month'); - fillDate(); - fillTime(); - }, - - fillDow = function () { - moment.locale(picker.options.language); - var html = $(''), weekdaysMin = moment.weekdaysMin(), i; - if (picker.options.calendarWeeks === true) { - html.append('#'); - } - if (moment().localeData()._week.dow === 0) { // starts on Sunday - for (i = 0; i < 7; i++) { - html.append('' + weekdaysMin[i] + ''); - } - } else { - for (i = 1; i < 8; i++) { - if (i === 7) { - html.append('' + weekdaysMin[0] + ''); - } else { - html.append('' + weekdaysMin[i] + ''); - } - } - } - picker.widget.find('.datepicker-days thead').append(html); - }, - - fillMonths = function () { - moment.locale(picker.options.language); - var html = '', i, monthsShort = moment.monthsShort(); - for (i = 0; i < 12; i++) { - html += '' + monthsShort[i] + ''; - } - picker.widget.find('.datepicker-months td').append(html); - }, - - fillDate = function () { - if (!picker.options.pickDate) { - return; - } - moment.locale(picker.options.language); - var year = picker.viewDate.year(), - month = picker.viewDate.month(), - startYear = picker.options.minDate.year(), - startMonth = picker.options.minDate.month(), - endYear = picker.options.maxDate.year(), - endMonth = picker.options.maxDate.month(), - currentDate, - prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months(); - - picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled'); - picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled'); - picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled'); - - picker.widget.find('.datepicker-days th:eq(1)').text( - months[month] + ' ' + year); - - prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months'); - days = prevMonth.daysInMonth(); - prevMonth.date(days).startOf('week'); - if ((year === startYear && month <= startMonth) || year < startYear) { - picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled'); - } - if ((year === endYear && month >= endMonth) || year > endYear) { - picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled'); - } - - nextMonth = moment(prevMonth).add(42, 'd'); - while (prevMonth.isBefore(nextMonth)) { - if (prevMonth.weekday() === moment().startOf('week').weekday()) { - row = $(''); - html.push(row); - if (picker.options.calendarWeeks === true) { - row.append('' + prevMonth.week() + ''); - } - } - clsName = ''; - if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) { - clsName += ' old'; - } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) { - clsName += ' new'; - } - if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) { - clsName += ' active'; - } - if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) { - clsName += ' disabled'; - } - if (picker.options.showToday === true) { - if (prevMonth.isSame(moment(), 'day')) { - clsName += ' today'; - } - } - if (picker.options.daysOfWeekDisabled) { - for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) { - if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) { - clsName += ' disabled'; - break; - } - } - } - row.append('' + prevMonth.date() + ''); - - currentDate = prevMonth.date(); - prevMonth.add(1, 'd'); - - if (currentDate === prevMonth.date()) { - prevMonth.add(1, 'd'); - } - } - picker.widget.find('.datepicker-days tbody').empty().append(html); - currentYear = picker.date.year(); - months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active'); - if (currentYear === year) { - months.eq(picker.date.month()).addClass('active'); - } - if (year - 1 < startYear) { - picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled'); - } - if (year + 1 > endYear) { - picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled'); - } - for (i = 0; i < 12; i++) { - if ((year === startYear && startMonth > i) || (year < startYear)) { - $(months[i]).addClass('disabled'); - } else if ((year === endYear && endMonth < i) || (year > endYear)) { - $(months[i]).addClass('disabled'); - } - } - - html = ''; - year = parseInt(year / 10, 10) * 10; - yearCont = picker.widget.find('.datepicker-years').find( - 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td'); - picker.widget.find('.datepicker-years').find('th').removeClass('disabled'); - if (startYear > year) { - picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled'); - } - if (endYear < year + 9) { - picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled'); - } - year -= 1; - for (i = -1; i < 11; i++) { - html += '' + year + ''; - year += 1; - } - yearCont.html(html); - }, - - fillHours = function () { - moment.locale(picker.options.language); - var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j; - table.parent().hide(); - if (picker.use24hours) { - current = 0; - for (i = 0; i < 6; i += 1) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += '' + padLeft(current.toString()) + ''; - current++; - } - html += ''; - } - } - else { - current = 1; - for (i = 0; i < 3; i += 1) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += '' + padLeft(current.toString()) + ''; - current++; - } - html += ''; - } - } - table.html(html); - }, - - fillMinutes = function () { - var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping; - table.parent().hide(); - if (step === 1) { - step = 5; - } - for (i = 0; i < Math.ceil(60 / step / 4) ; i++) { - html += ''; - for (j = 0; j < 4; j += 1) { - if (current < 60) { - html += '' + padLeft(current.toString()) + ''; - current += step; - } else { - html += ''; - } - } - html += ''; - } - table.html(html); - }, - - fillSeconds = function () { - var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j; - table.parent().hide(); - for (i = 0; i < 3; i++) { - html += ''; - for (j = 0; j < 4; j += 1) { - html += '' + padLeft(current.toString()) + ''; - current += 5; - } - html += ''; - } - table.html(html); - }, - - fillTime = function () { - if (!picker.date) { - return; - } - var timeComponents = picker.widget.find('.timepicker span[data-time-component]'), - hour = picker.date.hours(), - period = picker.date.format('A'); - if (!picker.use24hours) { - if (hour === 0) { - hour = 12; - } else if (hour !== 12) { - hour = hour % 12; - } - picker.widget.find('.timepicker [data-action=togglePeriod]').text(period); - } - timeComponents.filter('[data-time-component=hours]').text(padLeft(hour)); - timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes())); - timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second())); - }, - - click = function (e) { - e.stopPropagation(); - e.preventDefault(); - picker.unset = false; - var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date); - if (target.length === 1) { - if (!target.is('.disabled')) { - switch (target[0].nodeName.toLowerCase()) { - case 'th': - switch (target[0].className) { - case 'picker-switch': - showMode(1); - break; - case 'prev': - case 'next': - step = dpGlobal.modes[picker.viewMode].navStep; - if (target[0].className === 'prev') { - step = step * -1; - } - picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc); - fillDate(); - break; - } - break; - case 'span': - if (target.is('.month')) { - month = target.parent().find('span').index(target); - picker.viewDate.month(month); - } else { - year = parseInt(target.text(), 10) || 0; - picker.viewDate.year(year); - } - if (picker.viewMode === picker.minViewMode) { - picker.date = moment({ - y: picker.viewDate.year(), - M: picker.viewDate.month(), - d: picker.viewDate.date(), - h: picker.date.hours(), - m: picker.date.minutes(), - s: picker.date.seconds() - }); - set(); - notifyChange(oldDate, e.type); - } - showMode(-1); - fillDate(); - break; - case 'td': - if (target.is('.day')) { - day = parseInt(target.text(), 10) || 1; - month = picker.viewDate.month(); - year = picker.viewDate.year(); - if (target.is('.old')) { - if (month === 0) { - month = 11; - year -= 1; - } else { - month -= 1; - } - } else if (target.is('.new')) { - if (month === 11) { - month = 0; - year += 1; - } else { - month += 1; - } - } - picker.date = moment({ - y: year, - M: month, - d: day, - h: picker.date.hours(), - m: picker.date.minutes(), - s: picker.date.seconds() - } - ); - picker.viewDate = moment({ - y: year, M: month, d: Math.min(28, day) - }); - fillDate(); - set(); - notifyChange(oldDate, e.type); - } - break; - } - } - } - }, - - actions = { - incrementHours: function () { - checkDate('add', 'hours', 1); - }, - - incrementMinutes: function () { - checkDate('add', 'minutes', picker.options.minuteStepping); - }, - - incrementSeconds: function () { - checkDate('add', 'seconds', 1); - }, - - decrementHours: function () { - checkDate('subtract', 'hours', 1); - }, - - decrementMinutes: function () { - checkDate('subtract', 'minutes', picker.options.minuteStepping); - }, - - decrementSeconds: function () { - checkDate('subtract', 'seconds', 1); - }, - - togglePeriod: function () { - var hour = picker.date.hours(); - if (hour >= 12) { - hour -= 12; - } else { - hour += 12; - } - picker.date.hours(hour); - }, - - showPicker: function () { - picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide(); - picker.widget.find('.timepicker .timepicker-picker').show(); - }, - - showHours: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-hours').show(); - }, - - showMinutes: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-minutes').show(); - }, - - showSeconds: function () { - picker.widget.find('.timepicker .timepicker-picker').hide(); - picker.widget.find('.timepicker .timepicker-seconds').show(); - }, - - selectHour: function (e) { - var hour = parseInt($(e.target).text(), 10); - if (!picker.use24hours) { - if (picker.date.hours() >= 12) { - if (hour !== 12) { - hour += 12; - } - } else { - if (hour === 12) { - hour = 0; - } - } - } - picker.date.hours(hour); - actions.showPicker.call(picker); - }, - - selectMinute: function (e) { - picker.date.minutes(parseInt($(e.target).text(), 10)); - actions.showPicker.call(picker); - }, - - selectSecond: function (e) { - picker.date.seconds(parseInt($(e.target).text(), 10)); - actions.showPicker.call(picker); - } - }, - - doAction = function (e) { - var oldDate = moment(picker.date), - action = $(e.currentTarget).data('action'), - rv = actions[action].apply(picker, arguments); - stopEvent(e); - if (!picker.date) { - picker.date = moment({y: 1970}); - } - set(); - fillTime(); - notifyChange(oldDate, e.type); - return rv; - }, - - stopEvent = function (e) { - e.stopPropagation(); - e.preventDefault(); - }, - - keydown = function (e) { - if (e.keyCode === 27) { // allow escape to hide picker - picker.hide(); - } - }, - - change = function (e) { - moment.locale(picker.options.language); - var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict); - if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) { - update(); - picker.setValue(newDate); - notifyChange(oldDate, e.type); - set(); - } - else { - picker.viewDate = oldDate; - picker.unset = true; - notifyChange(oldDate, e.type); - notifyError(newDate); - } - }, - - showMode = function (dir) { - if (dir) { - picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir)); - } - picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show(); - }, - - attachDatePickerEvents = function () { - var $this, $parent, expanded, closed, collapseData; - picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks - picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks - picker.widget.on('mousedown', $.proxy(stopEvent, this)); - picker.element.on('keydown', $.proxy(keydown, this)); - if (picker.options.pickDate && picker.options.pickTime) { - picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) { - e.stopPropagation(); - $this = $(this); - $parent = $this.closest('ul'); - expanded = $parent.find('.in'); - closed = $parent.find('.collapse:not(.in)'); - - if (expanded && expanded.length) { - collapseData = expanded.data('collapse'); - if (collapseData && collapseData.transitioning) { - return; - } - expanded.collapse('hide'); - closed.collapse('show'); - $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); - if (picker.component) { - picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date); - } - } - }); - } - if (picker.isInput) { - picker.element.on({ - 'click': $.proxy(picker.show, this), - 'focus': $.proxy(picker.show, this), - 'change': $.proxy(change, this), - 'blur': $.proxy(picker.hide, this) - }); - } else { - picker.element.on({ - 'change': $.proxy(change, this) - }, 'input'); - if (picker.component) { - picker.component.on('click', $.proxy(picker.show, this)); - picker.component.on('mousedown', $.proxy(stopEvent, this)); - } else { - picker.element.on('click', $.proxy(picker.show, this)); - } - } - }, - - attachDatePickerGlobalEvents = function () { - $(window).on( - 'resize.datetimepicker' + picker.id, $.proxy(place, this)); - if (!picker.isInput) { - $(document).on( - 'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this)); - } - }, - - detachDatePickerEvents = function () { - picker.widget.off('click', '.datepicker *', picker.click); - picker.widget.off('click', '[data-action]'); - picker.widget.off('mousedown', picker.stopEvent); - if (picker.options.pickDate && picker.options.pickTime) { - picker.widget.off('click.togglePicker'); - } - if (picker.isInput) { - picker.element.off({ - 'focus': picker.show, - 'change': change, - 'click': picker.show, - 'blur' : picker.hide - }); - } else { - picker.element.off({ - 'change': change - }, 'input'); - if (picker.component) { - picker.component.off('click', picker.show); - picker.component.off('mousedown', picker.stopEvent); - } else { - picker.element.off('click', picker.show); - } - } - }, - - detachDatePickerGlobalEvents = function () { - $(window).off('resize.datetimepicker' + picker.id); - if (!picker.isInput) { - $(document).off('mousedown.datetimepicker' + picker.id); - } - }, - - isInFixed = function () { - if (picker.element) { - var parents = picker.element.parents(), inFixed = false, i; - for (i = 0; i < parents.length; i++) { - if ($(parents[i]).css('position') === 'fixed') { - inFixed = true; - break; - } - } - return inFixed; - } else { - return false; - } - }, - - set = function () { - moment.locale(picker.options.language); - var formatted = ''; - if (!picker.unset) { - formatted = moment(picker.date).format(picker.format); - } - getPickerInput().val(formatted); - picker.element.data('date', formatted); - if (!picker.options.pickTime) { - picker.hide(); - } - }, - - checkDate = function (direction, unit, amount) { - moment.locale(picker.options.language); - var newDate; - if (direction === 'add') { - newDate = moment(picker.date); - if (newDate.hours() === 23) { - newDate.add(amount, unit); - } - newDate.add(amount, unit); - } - else { - newDate = moment(picker.date).subtract(amount, unit); - } - if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) { - notifyError(newDate.format(picker.format)); - return; - } - - if (direction === 'add') { - picker.date.add(amount, unit); - } - else { - picker.date.subtract(amount, unit); - } - picker.unset = false; - }, - - isInDisableDates = function (date, timeUnit) { - moment.locale(picker.options.language); - var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict), - minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict); - - if (timeUnit) { - maxDate = maxDate.endOf(timeUnit); - minDate = minDate.startOf(timeUnit); - } - - if (date.isAfter(maxDate) || date.isBefore(minDate)) { - return true; - } - if (picker.options.disabledDates === false) { - return false; - } - return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true; - }, - isInEnableDates = function (date) { - moment.locale(picker.options.language); - if (picker.options.enabledDates === false) { - return true; - } - return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true; - }, - - indexGivenDates = function (givenDatesArray) { - // Store given enabledDates and disabledDates as keys. - // This way we can check their existence in O(1) time instead of looping through whole array. - // (for example: picker.options.enabledDates['2014-02-27'] === true) - var givenDatesIndexed = {}, givenDatesCount = 0, i; - for (i = 0; i < givenDatesArray.length; i++) { - if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) { - dDate = moment(givenDatesArray[i]); - } else { - dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict); - } - if (dDate.isValid()) { - givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; - givenDatesCount++; - } - } - if (givenDatesCount > 0) { - return givenDatesIndexed; - } - return false; - }, - - padLeft = function (string) { - string = string.toString(); - if (string.length >= 2) { - return string; - } - return '0' + string; - }, - - getTemplate = function () { - var - headTemplate = - '' + - '' + - '‹›' + - '' + - '', - contTemplate = - '', - template = '
' + - '' + headTemplate + '
' + - '
' + - '
' + - '' + headTemplate + contTemplate + '
' + - '
' + - '
' + - '' + headTemplate + contTemplate + '
' + - '
', - ret = ''; - if (picker.options.pickDate && picker.options.pickTime) { - ret = ''; - return ret; - } - if (picker.options.pickTime) { - return ( - '' - ); - } - return ( - '' - ); - }, - - dpGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'year', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'year', - navStep: 10 - } - ] - }, - - tpGlobal = { - hourTemplate: '', - minuteTemplate: '', - secondTemplate: '' - }; - - tpGlobal.getTemplate = function () { - return ( - '
' + - '' + - '' + - '' + - '' + - '' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '') + - '' + - '' + - ' ' + - '' + - ' ' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '' + - '') + - '' + - '' + - '' + - '' + - '' + - (picker.options.useSeconds ? - '' : '') + - (picker.use24hours ? '' : '') + - '' + - '
' + (picker.options.useMinutes ? '' : '') + '
' + tpGlobal.hourTemplate + ':' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '00') + ':' + tpGlobal.secondTemplate + '
' + (picker.options.useMinutes ? '' : '') + '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - (picker.options.useSeconds ? - '
' : '') - ); - }; - - picker.destroy = function () { - detachDatePickerEvents(); - detachDatePickerGlobalEvents(); - picker.widget.remove(); - picker.element.removeData('DateTimePicker'); - if (picker.component) { - picker.component.removeData('DateTimePicker'); - } - }; - - picker.show = function (e) { - if (getPickerInput().prop('disabled')) { - return; - } - if (picker.options.useCurrent) { - if (getPickerInput().val() === '') { - if (picker.options.minuteStepping !== 1) { - var mDate = moment(), - rInterval = picker.options.minuteStepping; - mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0); - picker.setValue(mDate.format(picker.format)); - } else { - picker.setValue(moment().format(picker.format)); - } - notifyChange('', e.type); - } - } - // if this is a click event on the input field and picker is already open don't hide it - if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) { - return; - } - if (picker.widget.hasClass('picker-open')) { - picker.widget.hide(); - picker.widget.removeClass('picker-open'); - } - else { - picker.widget.show(); - picker.widget.addClass('picker-open'); - } - picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight(); - place(); - picker.element.trigger({ - type: 'dp.show', - date: moment(picker.date) - }); - ////////MODIFICATION FOR COMPATIBILITY WITH OLD DATEPICKER - picker.element.trigger({ - type: 'show', - date: moment(picker.date).toDate(), - localDate: moment(picker.date).toDate() - }); - ///////END MODIFICATION FOR COMPATIBILTIY - attachDatePickerGlobalEvents(); - if (e) { - stopEvent(e); - } - }; - - picker.disable = function () { - var input = getPickerInput(); - if (input.prop('disabled')) { - return; - } - input.prop('disabled', true); - detachDatePickerEvents(); - }; - - picker.enable = function () { - var input = getPickerInput(); - if (!input.prop('disabled')) { - return; - } - input.prop('disabled', false); - attachDatePickerEvents(); - }; - - picker.hide = function () { - // Ignore event if in the middle of a picker transition - var collapse = picker.widget.find('.collapse'), i, collapseData; - for (i = 0; i < collapse.length; i++) { - collapseData = collapse.eq(i).data('collapse'); - if (collapseData && collapseData.transitioning) { - return; - } - } - picker.widget.hide(); - picker.widget.removeClass('picker-open'); - picker.viewMode = picker.startViewMode; - showMode(); - picker.element.trigger({ - type: 'dp.hide', - date: moment(picker.date) - }); - ////////MODIFICATION FOR COMPATIBILITY WITH OLD DATEPICKER - picker.element.trigger({ - type: 'hide', - date: moment(picker.date).toDate(), - localDate: moment(picker.date).toDate() - }); - ///////END MODIFICATION FOR COMPATIBILTIY - detachDatePickerGlobalEvents(); - }; - - picker.setValue = function (newDate) { - moment.locale(picker.options.language); - if (!newDate) { - picker.unset = true; - set(); - } else { - picker.unset = false; - } - if (!moment.isMoment(newDate)) { - newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict); - } else { - newDate = newDate.locale(picker.options.language); - } - if (newDate.isValid()) { - picker.date = newDate; - set(); - picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()}); - fillDate(); - fillTime(); - } - else { - notifyError(newDate); - } - }; - - picker.getDate = function () { - if (picker.unset) { - return null; - } - return moment(picker.date); - }; - - picker.setDate = function (date) { - var oldDate = moment(picker.date); - if (!date) { - picker.setValue(null); - } else { - picker.setValue(date); - } - notifyChange(oldDate, 'function'); - }; - - picker.setDisabledDates = function (dates) { - picker.options.disabledDates = indexGivenDates(dates); - if (picker.viewDate) { - update(); - } - }; - - picker.setEnabledDates = function (dates) { - picker.options.enabledDates = indexGivenDates(dates); - if (picker.viewDate) { - update(); - } - }; - - picker.setMaxDate = function (date) { - if (date === undefined) { - return; - } - if (moment.isMoment(date) || date instanceof Date) { - picker.options.maxDate = moment(date); - } else { - picker.options.maxDate = moment(date, picker.format, picker.options.useStrict); - } - if (picker.viewDate) { - update(); - } - }; - - picker.setMinDate = function (date) { - if (date === undefined) { - return; - } - if (moment.isMoment(date) || date instanceof Date) { - picker.options.minDate = moment(date); - } else { - picker.options.minDate = moment(date, picker.format, picker.options.useStrict); - } - if (picker.viewDate) { - update(); - } - }; - - init(); - }; - - $.fn.datetimepicker = function (options) { - - ////////MODIFICATION FOR COMPATIBILITY WITH OLD DATEPICKER - //store the orig method args - var methodArgs = arguments; - ///////END MODIFICATION FOR COMPATIBILTIY - - return this.each(function () { - var $this = $(this), - data = $this.data('DateTimePicker'); - if (!data) { - $this.data('DateTimePicker', new DateTimePicker(this, options)); - } - else { - ////////MODIFICATION FOR COMPATIBILITY WITH OLD DATEPICKER - //this is how the old api was accessed, now it is accessed directly by the - // .data("DateTimePicker") of the element that is assigned. - if (methodArgs.length == 0) { - return; - } - var method = data[methodArgs[0]]; - if (!(typeof method == "function")) { - return; - } - var args = []; - //remove first argument, note that arguments is not a true array! so we need to do this manually - for (var i = 1; i < methodArgs.length; i++) { - args.push(methodArgs[i]); - } - //call the method - method.apply(this, args); - - ///////END MODIFICATION FOR COMPATIBILTIY - } - }); - }; - - $.fn.datetimepicker.defaults = { - format: false, - pickDate: true, - pickTime: true, - useMinutes: true, - useSeconds: false, - useCurrent: true, - calendarWeeks: false, - minuteStepping: 1, - minDate: moment({y: 1900}), - maxDate: moment().add(100, 'y'), - showToday: true, - collapse: true, - language: moment.locale(), - defaultDate: '', - disabledDates: false, - enabledDates: false, - icons: {}, - useStrict: false, - direction: 'auto', - sideBySide: false, - daysOfWeekDisabled: [], - widgetParent: false - }; -})); diff --git a/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.min.css b/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.min.css deleted file mode 100644 index cf838a3c23..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/datetimepicker/bootstrap-datetimepicker.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Datetimepicker for Bootstrap v3 -//! version : 3.1.3 - * https://github.com/Eonasdan/bootstrap-datetimepicker/ - */.bootstrap-datetimepicker-widget{top:0;left:0;width:250px;padding:4px;margin-top:1px;z-index:99999!important;border-radius:4px}.bootstrap-datetimepicker-widget.timepicker-sbs{width:600px}.bootstrap-datetimepicker-widget.bottom:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:7px}.bootstrap-datetimepicker-widget.bottom:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:8px}.bootstrap-datetimepicker-widget.top:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.top:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;position:absolute;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget .dow{width:14.2857%}.bootstrap-datetimepicker-widget.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget>ul{list-style-type:none;margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:700;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator{width:4px;padding:0;margin:0}.bootstrap-datetimepicker-widget .datepicker>div{display:none}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget td,.bootstrap-datetimepicker-widget th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget td.cw{font-size:10px;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget td.day:hover,.bootstrap-datetimepicker-widget td.hour:hover,.bootstrap-datetimepicker-widget td.minute:hover,.bootstrap-datetimepicker-widget td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget td.old,.bootstrap-datetimepicker-widget td.new{color:#777}.bootstrap-datetimepicker-widget td.today{position:relative}.bootstrap-datetimepicker-widget td.today:before{content:'';display:inline-block;border-left:7px solid transparent;border-bottom:7px solid #428bca;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget td.active,.bootstrap-datetimepicker-widget td.active:hover{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget td.disabled,.bootstrap-datetimepicker-widget td.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget td span:hover{background:#eee}.bootstrap-datetimepicker-widget td span.active{background-color:#428bca;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget td span.old{color:#777}.bootstrap-datetimepicker-widget td span.disabled,.bootstrap-datetimepicker-widget td span.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget th.picker-switch{width:145px}.bootstrap-datetimepicker-widget th.next,.bootstrap-datetimepicker-widget th.prev{font-size:21px}.bootstrap-datetimepicker-widget th.disabled,.bootstrap-datetimepicker-widget th.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget thead tr:first-child th:hover{background:#eee}.input-group.date .input-group-addon span{display:block;cursor:pointer;width:16px;height:16px}.bootstrap-datetimepicker-widget.left-oriented:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.left-oriented:after{left:auto;right:7px}.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody>tr>td{padding:0!important}@media screen and (max-width:767px){.bootstrap-datetimepicker-widget.timepicker-sbs{width:283px}} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js deleted file mode 100644 index 8d2b83d065..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js +++ /dev/null @@ -1,186 +0,0 @@ -/** -@ngdoc directive -@name umbraco.directives.directive:umbDateTimePicker -@restrict E -@scope - -@description -Added in Umbraco version 7.6 -This directive is a wrapper of the bootstrap datetime picker version 3.1.3. Use it to render a date time picker. -For extra details about options and events take a look here: https://eonasdan.github.io/bootstrap-datetimepicker/ - -Use this directive to render a date time picker - -

Markup example

-
-	
- - - - -
-
- -

Controller example

-
-	(function () {
-		"use strict";
-
-		function Controller() {
-
-            var vm = this;
-
-            vm.date = "";
-
-            vm.config = {
-                pickDate: true,
-                pickTime: true,
-                useSeconds: true,
-                format: "YYYY-MM-DD HH:mm:ss",
-                icons: {
-                    time: "icon-time",
-                    date: "icon-calendar",
-                    up: "icon-chevron-up",
-                    down: "icon-chevron-down"
-                }
-            };
-
-            vm.datePickerChange = datePickerChange;
-            vm.datePickerError = datePickerError;
-
-            function datePickerChange(event) {
-                // handle change
-                if(event.date && event.date.isValid()) {
-                    var date = event.date.format(vm.datePickerConfig.format);
-                }
-            }
-
-            function datePickerError(event) {
-                // handle error
-            }
-
-        }
-
-		angular.module("umbraco").controller("My.Controller", Controller);
-
-	})();
-
- -@param {object} options (binding): Config object for the date picker. -@param {callback} onHide (callback): Hide callback. -@param {callback} onShow (callback): Show callback. -@param {callback} onChange (callback): Change callback. -@param {callback} onError (callback): Error callback. -@param {callback} onUpdate (callback): Update callback. -**/ - -(function () { - 'use strict'; - - function DateTimePickerDirective(assetsService) { - - function link(scope, element, attrs, ctrl) { - - scope.hasTranscludedContent = false; - - function onInit() { - - // check for transcluded content so we can hide the defualt markup - scope.hasTranscludedContent = element.find('.js-datePicker__transcluded-content')[0].children.length > 0; - - // load css file for the date picker - assetsService.loadCss('lib/datetimepicker/bootstrap-datetimepicker.min.css', scope); - - // load the js file for the date picker - assetsService.loadJs('lib/datetimepicker/bootstrap-datetimepicker.js', scope).then(function () { - // init date picker - initDatePicker(); - }); - } - - function onHide(event) { - if (scope.onHide) { - scope.$apply(function(){ - // callback - scope.onHide({event: event}); - }); - } - } - - function onShow() { - if (scope.onShow) { - scope.$apply(function(){ - // callback - scope.onShow(); - }); - } - } - - function onChange(event) { - if (scope.onChange && event.date && event.date.isValid()) { - scope.$apply(function(){ - // callback - scope.onChange({event: event}); - }); - } - } - - function onError(event) { - if (scope.onError) { - scope.$apply(function(){ - // callback - scope.onError({event:event}); - }); - } - } - - function onUpdate(event) { - if (scope.onUpdate) { - scope.$apply(function(){ - // callback - scope.onUpdate({event: event}); - }); - } - } - - function initDatePicker() { - // Open the datepicker and add a changeDate eventlistener - element - .datetimepicker(scope.options) - .on("dp.hide", onHide) - .on("dp.show", onShow) - .on("dp.change", onChange) - .on("dp.error", onError) - .on("dp.update", onUpdate); - } - - onInit(); - - } - - var directive = { - restrict: 'E', - replace: true, - transclude: true, - templateUrl: 'views/components/umb-date-time-picker.html', - scope: { - options: "=", - onHide: "&", - onShow: "&", - onChange: "&", - onError: "&", - onUpdate: "&" - }, - link: link - }; - - return directive; - - } - - angular.module('umbraco.directives').directive('umbDateTimePicker', DateTimePickerDirective); - -})(); From bd23cbed20caea3d768f5992e7ad051ca1e80cad Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 19 Nov 2018 15:50:11 +0100 Subject: [PATCH 11/60] null checks clean up debug data --- .../datepicker/datepicker.controller.js | 33 +++++++++---------- .../datepicker/datepicker.html | 11 ------- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js index e673b17a73..704fccbde1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js @@ -45,31 +45,28 @@ function dateTimePickerController($scope, notificationsService, assetsService, a $scope.serverTimeNeedsOffsetting = (-serverOffset !== localOffset); } - //get the current user to see if we can localize this picker - userService.getCurrentUser().then(function (user) { + const dateFormat = $scope.model.config.pickTime ? "Y-m-d H:i:S" : "Y-m-d"; - const dateFormat = $scope.model.config.pickTime ? "Y-m-d H:i:S" : "Y-m-d"; - - // date picker config - $scope.datePickerConfig = { - enableTime: $scope.model.config.pickTime, - dateFormat: dateFormat, - time_24hr: true - }; - - $scope.model.config.language = user.locale; - - setDatePickerVal(); + // date picker config + $scope.datePickerConfig = { + enableTime: $scope.model.config.pickTime, + dateFormat: dateFormat, + time_24hr: true + }; - }); + setDatePickerVal(); } $scope.clearDate = function() { $scope.hasDatetimePickerValue = false; - $scope.model.datetimePickerValue = null; - $scope.model.value = null; - $scope.datePickerForm.datepicker.$setValidity("pickerError", true); + if($scope.model) { + $scope.model.datetimePickerValue = null; + $scope.model.value = null; + } + if($scope.datePickerForm && $scope.datePickerForm.datepicker) { + $scope.datePickerForm.datepicker.$setValidity("pickerError", true); + } } $scope.datePickerSetup = function(instance) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index f9b5271e0a..47c9182650 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -42,16 +42,5 @@ Clear date

-
-
-
model.value
- {{model.value}} -
-
-
Date time picker value
- {{model.datetimePickerValue}} -
-
- From f24a347b01fb577f096bb3c71566500ff3a653f7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 22 Nov 2018 10:06:00 +0100 Subject: [PATCH 12/60] load in new slider + basic setup --- src/Umbraco.Web.UI.Client/gulpfile.js | 8 + src/Umbraco.Web.UI.Client/package.json | 1 + .../components/umbrangeslider.directive.js | 148 ++++++++++++++++++ .../slider/slider.controller.js | 80 +++++----- .../views/propertyeditors/slider/slider.html | 14 ++ 5 files changed, 210 insertions(+), 41 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index b773025e7c..0dd816ae16 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -349,6 +349,14 @@ gulp.task('dependencies', function () { "src": ["./node_modules/ng-file-upload/dist/ng-file-upload.min.js"], "base": "./node_modules/ng-file-upload/dist" }, + { + "name": "nouislider", + "src": [ + "./node_modules/nouislider/distribute/nouislider.min.js", + "./node_modules/nouislider/distribute/nouislider.min.css" + ], + "base": "./node_modules/nouislider/distribute" + }, { "name": "signalr", "src": ["./node_modules/signalr/jquery.signalR.js"], diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 69c046624f..d847e14e59 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -33,6 +33,7 @@ "lazyload-js": "1.0.0", "moment": "2.10.6", "ng-file-upload": "12.2.13", + "nouislider": "12.1.0", "npm": "^6.4.1", "signalr": "2.3.0", "tinymce": "4.7.13", diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js new file mode 100644 index 0000000000..c8a22693e3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js @@ -0,0 +1,148 @@ +(function() { + 'use strict'; + + var umbRangeSlider = { + template: '
', + controller: UmbRangeSliderController, + bindings: { + ngModel: '<', + options: '<', + onSetup: '&?', + onUpdate: '&?', + onSlide: '&?', + onSet: '&?', + onChange: '&?', + onStart: '&?', + onEnd: '&?' + } + }; + + function UmbRangeSliderController($element, $timeout, $scope, assetsService) { + + const ctrl = this; + let sliderInstance = null; + + ctrl.$onInit = function() { + + // load css file for the date picker + assetsService.loadCss('lib/nouislider/nouislider.min.css', $scope); + + // load the js file for the date picker + assetsService.loadJs('lib/nouislider/nouislider.min.js', $scope).then(function () { + // init date picker + grabElementAndRun(); + }); + + }; + + function grabElementAndRun() { + $timeout(function() { + const element = $element.find('.umb-range-slider')[0]; + setSlider(element); + }, 0, true); + } + + function setSlider(element) { + + sliderInstance = element; + + const defaultOptions = { + "start": [0], + "step": 1, + "range": { + "min": [0], + "max": [100] + } + }; + const options = ctrl.options ? ctrl.options : defaultOptions; + + // create new slider + noUiSlider.create(sliderInstance, options); + + if (ctrl.onSetup) { + ctrl.onSetup({ + slider: sliderInstance + }); + } + + // If has ngModel set the date + if (ctrl.ngModel) { + sliderInstance.noUiSlider.set(ctrl.ngModel); + } + + // destroy the flatpickr instance when the dom element is removed + angular.element(element).on('$destroy', function() { + sliderInstance.noUiSlider.off(); + }); + + setUpCallbacks(); + + // Refresh the scope + $scope.$applyAsync(); + } + + function setUpCallbacks() { + if(sliderInstance) { + + // bind hook for update + if(ctrl.onUpdate) { + sliderInstance.noUiSlider.on('update', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onUpdate({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + // bind hook for slide + if(ctrl.onSlide) { + sliderInstance.noUiSlider.on('slide', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onSlide({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + // bind hook for set + if(ctrl.onSet) { + sliderInstance.noUiSlider.on('set', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onSet({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + // bind hook for change + if(ctrl.onChange) { + sliderInstance.noUiSlider.on('change', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onChange({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + // bind hook for start + if(ctrl.onStart) { + sliderInstance.noUiSlider.on('start', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onStart({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + // bind hook for end + if(ctrl.onEnd) { + sliderInstance.noUiSlider.on('end', function (values, handle, unencoded, tap, positions) { + $timeout(function() { + ctrl.onEnd({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions}); + }); + }); + } + + } + } + + } + + angular.module('umbraco.directives').component('umbRangeSlider', umbRangeSlider); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index 588e2d2b03..f991700dd7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -1,50 +1,18 @@ function sliderController($scope, $log, $element, assetsService, angularHelper) { - var sliderRef = null; + let sliderRef = null; /** configure some defaults on init */ function configureDefaults() { - - if (!$scope.model.config.orientation) { - $scope.model.config.orientation = "horizontal"; - } - if (!$scope.model.config.enableRange) { - $scope.model.config.enableRange = false; - } - else { - $scope.model.config.enableRange = Object.toBoolean($scope.model.config.enableRange); - } - if (!$scope.model.config.initVal1) { - $scope.model.config.initVal1 = 0; - } - else { - $scope.model.config.initVal1 = parseFloat($scope.model.config.initVal1); - } - if (!$scope.model.config.initVal2) { - $scope.model.config.initVal2 = 0; - } - else { - $scope.model.config.initVal2 = parseFloat($scope.model.config.initVal2); - } - if (!$scope.model.config.minVal) { - $scope.model.config.minVal = 0; - } - else { - $scope.model.config.minVal = parseFloat($scope.model.config.minVal); - } - if (!$scope.model.config.maxVal) { - $scope.model.config.maxVal = 100; - } - else { - $scope.model.config.maxVal = parseFloat($scope.model.config.maxVal); - } - if (!$scope.model.config.step) { - $scope.model.config.step = 1; - } - else { - $scope.model.config.step = parseFloat($scope.model.config.step); - } + $scope.model.config.orientation = $scope.model.config.orientation ? $scope.model.config.orientation : "horizontal"; + $scope.model.config.enableRange = $scope.model.config.enableRange ? Object.toBoolean($scope.model.config.enableRange) : false; + $scope.model.config.initVal1 = $scope.model.config.initVal1 ? parseFloat($scope.model.config.initVal1) : 0; + $scope.model.config.initVal2 = $scope.model.config.initVal2 ? parseFloat($scope.model.config.initVal2) : 0; + $scope.model.config.minVal = $scope.model.config.minVal ? parseFloat($scope.model.config.minVal) : 0; + $scope.model.config.maxVal = $scope.model.config.maxVal ? parseFloat($scope.model.config.maxVal) : 100; + $scope.model.config.step = $scope.model.config.step ? parseFloat($scope.model.config.step) : 1; + if (!$scope.model.config.handle) { $scope.model.config.handle = "round"; @@ -209,10 +177,40 @@ } } + function setModelValue(values) { + $scope.model.value = values.toString(); + } + + $scope.setup = function(slider) { + sliderRef = slider; + }; + + $scope.update = function(values) { + setModelValue(values); + }; + function init() { configureDefaults(); + // format config to fit slider plugin + const start = $scope.model.config.enableRange ? [$scope.model.config.initVal1, $scope.model.config.initVal2] : [$scope.model.config.initVal1]; + const step = $scope.model.config.step; + const tooltips = $scope.model.config.enableRange ? [true, true] : [true]; + const min = $scope.model.config.minVal ? [$scope.model.config.minVal] : [$scope.model.config.minVal]; + const max = $scope.model.config.maxVal ? [$scope.model.config.maxVal] : [$scope.model.config.maxVal]; + + // setup default + $scope.sliderOptions = { + "start": start, + "step": step, + "tooltips": tooltips, + "range": { + "min": min, + "max": max + } + }; + //tell the assetsService to load the bootstrap slider //libs from the plugin folder assetsService diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index 638ecead4b..4bbe6448ba 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,5 +1,19 @@ 
+ +
+ + +
+ +
Value
+ {{model.value}} +
config
+
{{model.config | json}}
From e54e1989babd64b2aa89d743d5ef52ca72763c99 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 22 Nov 2018 10:52:48 +0100 Subject: [PATCH 13/60] format numbers to not have decimals --- .../src/views/propertyeditors/slider/slider.controller.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index f991700dd7..442f35466e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -205,6 +205,14 @@ "start": start, "step": step, "tooltips": tooltips, + "format": { + to: function (value) { + return Math.round(value); + }, + from: function (value) { + return Math.round(value); + } + }, "range": { "min": min, "max": max From fee968b94eb64801301ce7d64bee9d372922cb1d Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 26 Nov 2018 08:19:49 +0100 Subject: [PATCH 14/60] Make MoveOperationStatusType of underlying type byte to fix move and copy YSODs --- src/Umbraco.Core/Services/MoveOperationStatusType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/MoveOperationStatusType.cs b/src/Umbraco.Core/Services/MoveOperationStatusType.cs index 95ccce93ca..b4b4c2b42e 100644 --- a/src/Umbraco.Core/Services/MoveOperationStatusType.cs +++ b/src/Umbraco.Core/Services/MoveOperationStatusType.cs @@ -7,7 +7,7 @@ /// /// Anything less than 10 = Success! /// - public enum MoveOperationStatusType + public enum MoveOperationStatusType : byte { /// /// The move was successful. From f4728e5b83231b9670779f762523523a3824192c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 11:18:23 +0100 Subject: [PATCH 15/60] add custom styling + add pips --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/components/umb-range-slider.less | 39 +++++++++++++++++++ .../slider/slider.controller.js | 10 +++++ 3 files changed, 50 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-range-slider.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index a3d5374491..faf8bb945b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -151,6 +151,7 @@ @import "components/umb-number-badge.less"; @import "components/umb-progress-circle.less"; @import "components/umb-stylesheet.less"; +@import "components/umb-range-slider.less"; @import "components/buttons/umb-button.less"; @import "components/buttons/umb-button-group.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-range-slider.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-range-slider.less new file mode 100644 index 0000000000..1c21c5a148 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-range-slider.less @@ -0,0 +1,39 @@ + + +.umb-range-slider.noUi-target { + background: linear-gradient(to bottom, #f5f5f5 0%, #f9f9f9 100%); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + border-radius: 20px; + height: 10px; + border: none; +} + +.umb-range-slider .noUi-handle { + border-radius: 100px; + border: none; + box-shadow: none; + width: 20px !important; + height: 20px !important; + background-color: @turquoise; +} + +.umb-range-slider .noUi-handle::before { + display: none; +} + +.umb-range-slider .noUi-handle::after { + display: none; +} + +.umb-range-slider .noUi-handle { + right: -10px !important; // half the handle width +} + +.umb-range-slider .noUi-marker-large.noUi-marker-horizontal { + height: 10px; +} + +.umb-range-slider .noUi-marker.noUi-marker-horizontal { + width: 1px; +} + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index 442f35466e..e62e2e7e40 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -216,9 +216,19 @@ "range": { "min": min, "max": max + }, + "pips": { + mode: 'steps', + density: 100, + filter: filterPips } }; + function filterPips(value, type) { + // show a pip for min and maximum value + return value === $scope.model.config.minVal || value === $scope.model.config.maxVal ? 1 : -1; + } + //tell the assetsService to load the bootstrap slider //libs from the plugin folder assetsService From 6257416c4a3f3797c40ff6a396dcaed734fa8463 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 11:38:15 +0100 Subject: [PATCH 16/60] remove a bunch of slider prevalues. --- .../PropertyEditors/SliderConfiguration.cs | 36 ------------------- .../slider/handle.prevalues.html | 13 ------- .../slider/orientation.prevalues.html | 12 ------- .../slider/tooltip.prevalues.html | 13 ------- 4 files changed, 74 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/orientation.prevalues.html delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/tooltip.prevalues.html diff --git a/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs b/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs index b2bf99bdc6..55ca199121 100644 --- a/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs @@ -8,9 +8,6 @@ [ConfigurationField("enableRange", "Enable range", "boolean")] public bool EnableRange { get; set; } - [ConfigurationField("orientation", "Orientation", "views/propertyeditors/slider/orientation.prevalues.html")] - public string Orientation { get; set; } - [ConfigurationField("initVal1", "Initial value", "number")] public int InitialValue { get; set; } @@ -25,38 +22,5 @@ [ConfigurationField("step", "Step increments", "number")] public int StepIncrements { get; set; } - - [ConfigurationField("precision", "Precision", "number", Description = "The number of digits shown after the decimal. Defaults to the number of digits after the decimal of step value.")] - public int Precision { get; set; } - - [ConfigurationField("handle", "Handle", "views/propertyeditors/slider/handle.prevalues.html", Description = "Handle shape. Default is 'round\'")] - public string Handle { get; set; } - - [ConfigurationField("tooltip", "Tooltip", "views/propertyeditors/slider/tooltip.prevalues.html", Description = "Whether to show the tooltip on drag, hide the tooltip, or always show the tooltip. Accepts: 'show', 'hide', or 'always'")] - public string Tooltip { get; set; } - - [ConfigurationField("tooltipSplit", "Tooltip split", "boolean", Description = "If false show one tootip if true show two tooltips one for each handler")] - public bool TooltipSplit { get; set; } // fixme bool? - - [ConfigurationField("tooltipFormat", "Tooltip format", "textstring", Description = "The value wanted to be displayed in the tooltip. Use {0} and {1} for current values - {1} is only for range slider and if not using tooltip split.")] - public string TooltipFormat { get; set; } - - [ConfigurationField("tooltipPosition", "Tooltip position", "textstring", Description = "Position of tooltip, relative to slider. Accepts 'top'/'bottom' for horizontal sliders and 'left'/'right' for vertically orientated sliders. Default positions are 'top' for horizontal and 'right' for vertical slider.")] - public string TooltipPosition { get; set; } - - [ConfigurationField("reversed", "Reversed", "boolean", Description = "Whether or not the slider should be reversed")] - public bool Reversed { get; set; } // fixme bool? - - [ConfigurationField("ticks", "Ticks", "textstring", Description = "Comma-separated values. Used to define the values of ticks. Tick marks are indicators to denote special values in the range. This option overwrites min and max options.")] - public string Ticks { get; set; } - - [ConfigurationField("ticksPositions", "Ticks positions", "textstring", Description = "Comma-separated values. Defines the positions of the tick values in percentages. The first value should always be 0, the last value should always be 100 percent.")] - public string TicksPositions { get; set; } - - [ConfigurationField("ticksLabels", "Ticks labels", "textstring", Description = "Comma-separated values. Defines the labels below the tick marks. Accepts HTML input.")] - public string TicksLabels { get; set; } - - [ConfigurationField("ticksSnapBounds", "Ticks snap bounds", "number", Description = "Used to define the snap bounds of a tick. Snaps to the tick if value is within these bounds.")] - public int TicksSnapBounds { get; set; } } } 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 deleted file mode 100644 index 0821c5e757..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/handle.prevalues.html +++ /dev/null @@ -1,13 +0,0 @@ -
- - - - - Required - - -
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/orientation.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/orientation.prevalues.html deleted file mode 100644 index 05fb6756d1..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/orientation.prevalues.html +++ /dev/null @@ -1,12 +0,0 @@ -
- - - - - Required - - -
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/tooltip.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/tooltip.prevalues.html deleted file mode 100644 index 415a39d3bd..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/tooltip.prevalues.html +++ /dev/null @@ -1,13 +0,0 @@ -
- - - - - Required - - -
From e169de917da459506bcadfe6832d7acb32888eee Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 11:53:52 +0100 Subject: [PATCH 17/60] remove unused config --- .../slider/slider.controller.js | 85 ------------------- 1 file changed, 85 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index e62e2e7e40..292ea888cd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -4,84 +4,12 @@ /** configure some defaults on init */ function configureDefaults() { - - $scope.model.config.orientation = $scope.model.config.orientation ? $scope.model.config.orientation : "horizontal"; $scope.model.config.enableRange = $scope.model.config.enableRange ? Object.toBoolean($scope.model.config.enableRange) : false; $scope.model.config.initVal1 = $scope.model.config.initVal1 ? parseFloat($scope.model.config.initVal1) : 0; $scope.model.config.initVal2 = $scope.model.config.initVal2 ? parseFloat($scope.model.config.initVal2) : 0; $scope.model.config.minVal = $scope.model.config.minVal ? parseFloat($scope.model.config.minVal) : 0; $scope.model.config.maxVal = $scope.model.config.maxVal ? parseFloat($scope.model.config.maxVal) : 100; $scope.model.config.step = $scope.model.config.step ? parseFloat($scope.model.config.step) : 1; - - - if (!$scope.model.config.handle) { - $scope.model.config.handle = "round"; - } - - if (!$scope.model.config.reversed) { - $scope.model.config.reversed = false; - } - else { - $scope.model.config.reversed = Object.toBoolean($scope.model.config.reversed); - } - - if (!$scope.model.config.tooltip) { - $scope.model.config.tooltip = "show"; - } - - if (!$scope.model.config.tooltipSplit) { - $scope.model.config.tooltipSplit = false; - } - else { - $scope.model.config.tooltipSplit = Object.toBoolean($scope.model.config.tooltipSplit); - } - - if ($scope.model.config.tooltipFormat) { - $scope.model.config.formatter = function (value) { - if (angular.isArray(value) && $scope.model.config.enableRange) { - return $scope.model.config.tooltipFormat.replace("{0}", value[0]).replace("{1}", value[1]); - } else { - return $scope.model.config.tooltipFormat.replace("{0}", value); - } - } - } - - if (!$scope.model.config.ticks) { - $scope.model.config.ticks = []; - } - else if (angular.isString($scope.model.config.ticks)) { - // returns comma-separated string to an array, e.g. [0, 100, 200, 300, 400] - $scope.model.config.ticks = _.map($scope.model.config.ticks.split(','), function (item) { - return parseInt(item.trim()); - }); - } - - if (!$scope.model.config.ticksPositions) { - $scope.model.config.ticksPositions = []; - } - else if (angular.isString($scope.model.config.ticksPositions)) { - // returns comma-separated string to an array, e.g. [0, 30, 60, 70, 90, 100] - $scope.model.config.ticksPositions = _.map($scope.model.config.ticksPositions.split(','), function (item) { - return parseInt(item.trim()); - }); - } - - if (!$scope.model.config.ticksLabels) { - $scope.model.config.ticksLabels = []; - } - else if (angular.isString($scope.model.config.ticksLabels)) { - // returns comma-separated string to an array, e.g. ['$0', '$100', '$200', '$300', '$400'] - $scope.model.config.ticksLabels = _.map($scope.model.config.ticksLabels.split(','), function (item) { - return item.trim(); - }); - } - - if (!$scope.model.config.ticksSnapBounds) { - $scope.model.config.ticksSnapBounds = 0; - } - else { - $scope.model.config.ticksSnapBounds = parseFloat($scope.model.config.ticksSnapBounds); - } } function getValueForSlider(val) { @@ -138,20 +66,7 @@ var slider = $element.find('.slider-item').bootstrapSlider({ max: $scope.model.config.maxVal, min: $scope.model.config.minVal, - orientation: $scope.model.config.orientation, - selection: $scope.model.config.reversed ? "after" : "before", step: $scope.model.config.step, - precision: $scope.model.config.precision, - tooltip: $scope.model.config.tooltip, - tooltip_split: $scope.model.config.tooltipSplit, - tooltip_position: $scope.model.config.tooltipPosition, - handle: $scope.model.config.handle, - reversed: $scope.model.config.reversed, - ticks: $scope.model.config.ticks, - ticks_positions: $scope.model.config.ticksPositions, - ticks_labels: $scope.model.config.ticksLabels, - ticks_snap_bounds: $scope.model.config.ticksSnapBounds, - formatter: $scope.model.config.formatter, range: $scope.model.config.enableRange, //set the slider val - we cannot do this with data- attributes when using ranges value: sliderVal From 16b57ac022765a703861a152eebbd8a446109844 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 13:46:47 +0100 Subject: [PATCH 18/60] remove bootstrap logic from slider controller --- .../slider/slider.controller.js | 127 ++---------------- .../views/propertyeditors/slider/slider.html | 13 +- 2 files changed, 17 insertions(+), 123 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index 292ea888cd..c8813ee4c0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -1,4 +1,4 @@ -function sliderController($scope, $log, $element, assetsService, angularHelper) { +function sliderController($scope) { let sliderRef = null; @@ -12,100 +12,23 @@ $scope.model.config.step = $scope.model.config.step ? parseFloat($scope.model.config.step) : 1; } - function getValueForSlider(val) { - - if (!angular.isArray(val)) { - val = val.toString().split(","); - } - var val1 = val[0]; - var val2 = val.length > 1 ? val[1] : null; - - //configure the model value based on if range is enabled or not - if ($scope.model.config.enableRange == true) { - var i1 = parseFloat(val1); - var i2 = parseFloat(val2); - return [ - isNaN(i1) ? $scope.model.config.minVal : (i1 >= $scope.model.config.minVal ? i1 : $scope.model.config.minVal), - isNaN(i2) ? $scope.model.config.maxVal : (i2 >= i1 ? (i2 <= $scope.model.config.maxVal ? i2 : $scope.model.config.maxVal) : $scope.model.config.maxVal) - ]; - } - else { - return parseFloat(val1); - } - } - - /** This creates the slider with the model values - it's called on startup and returns a reference to the slider object */ - function createSlider() { - - //the value that we'll give the slider - if it's a range, we store our value as a comma separated val but this slider expects an array - var sliderVal = null; - - //configure the model value based on if range is enabled or not - if ($scope.model.config.enableRange == true) { - //If no value saved yet - then use default value - //If it contains a single value - then also create a new array value - if (!$scope.model.value || $scope.model.value.indexOf(",") == -1) { - sliderVal = getValueForSlider([$scope.model.config.initVal1, $scope.model.config.initVal2]); - } - else { - //this will mean it's a delimited value stored in the db, convert it to an array - sliderVal = getValueForSlider($scope.model.value.split(',')); - } - } - else { - //If no value saved yet - then use default value - if ($scope.model.value) { - sliderVal = getValueForSlider($scope.model.value); - } - else { - sliderVal = getValueForSlider($scope.model.config.initVal1); - } - } - - //initiate slider, add event handler and get the instance reference (stored in data) - var slider = $element.find('.slider-item').bootstrapSlider({ - max: $scope.model.config.maxVal, - min: $scope.model.config.minVal, - step: $scope.model.config.step, - range: $scope.model.config.enableRange, - //set the slider val - we cannot do this with data- attributes when using ranges - value: sliderVal - }); - - slider.on('slideStop', function (e) { - var value = e.value; - angularHelper.safeApply($scope, function () { - $scope.model.value = getModelValueFromSlider(value); - }); - }).data('slider'); - - return slider; - } - - function getModelValueFromSlider(sliderVal) { - //Get the value from the slider and format it correctly, if it is a range we want a comma delimited value - if ($scope.model.config.enableRange == true) { - return sliderVal.join(","); - } - else { - return sliderVal.toString(); - } - } - function setModelValue(values) { - $scope.model.value = values.toString(); + $scope.model.value = values ? values.toString() : null; } $scope.setup = function(slider) { sliderRef = slider; }; - $scope.update = function(values) { + $scope.end = function(values) { setModelValue(values); }; function init() { + // convert to array + $scope.sliderValue = $scope.model.value ? $scope.model.value.split(',') : null; + configureDefaults(); // format config to fit slider plugin @@ -139,41 +62,19 @@ } }; - function filterPips(value, type) { + function filterPips(value) { // show a pip for min and maximum value return value === $scope.model.config.minVal || value === $scope.model.config.maxVal ? 1 : -1; } - //tell the assetsService to load the bootstrap slider - //libs from the plugin folder - assetsService - .loadJs("lib/slider/js/bootstrap-slider.js") - .then(function () { - - var slider = createSlider(); - - // Initialize model value if not set - if (!$scope.model.value) { - var sliderVal = slider.bootstrapSlider('getValue'); - $scope.model.value = getModelValueFromSlider(sliderVal); - } - - //watch for the model value being changed and update the slider value when it does - $scope.$watch("model.value", function (newVal, oldVal) { - if (newVal != oldVal) { - var sliderVal = getModelValueFromSlider(slider.bootstrapSlider('getValue')); - if (newVal !== sliderVal) { - slider.bootstrapSlider('setValue', getValueForSlider(newVal)); - } - } - }); - - }); - - //load the separate css for the editor to avoid it blocking our js loading - assetsService.loadCss("lib/slider/bootstrap-slider.css", $scope); - assetsService.loadCss("lib/slider/bootstrap-slider-custom.css", $scope); } + + $scope.$watch('model.value', function(newValue, oldValue){ + if(newValue && newValue !== oldValue) { + $scope.sliderValue = newValue.split(','); + sliderRef.noUiSlider.set($scope.sliderValue); + } + }) init(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index 4bbe6448ba..c147b30b23 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,19 +1,12 @@ 
- - -
+
+ on-end="end(values)">
-
Value
- {{model.value}} -
config
-
{{model.config | json}}
-
From d314361996d702ab997eb000766ae22012c8b7ab Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 14:28:51 +0100 Subject: [PATCH 19/60] delete bootstrap slider javascript and css files --- .../lib/slider/bootstrap-slider-custom.css | 79 - .../lib/slider/bootstrap-slider.css | 255 --- .../lib/slider/js/bootstrap-slider.js | 1553 ----------------- 3 files changed, 1887 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider-custom.css delete mode 100644 src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider.css delete mode 100644 src/Umbraco.Web.UI.Client/lib/slider/js/bootstrap-slider.js diff --git a/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider-custom.css b/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider-custom.css deleted file mode 100644 index e7a395d458..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider-custom.css +++ /dev/null @@ -1,79 +0,0 @@ -/* set default selection color */ -.slider-track .slider-selection { - background: #89cdef; -} - -/* custom styling for triangle */ -.slider.slider-horizontal .slider-tick.triangle, -.slider.slider-horizontal .slider-handle.triangle { - box-shadow: none; - border-width: 0 12px 15px 12px !important; - margin-left: -12px; - margin-top: -5px !important; -} - -.slider.slider-vertical .slider-tick.triangle, -.slider.slider-vertical .slider-handle.triangle { - box-shadow: none; - border-width: 12px 0 12px 15px !important; - margin-top: -12px; -} - -/* for custom handle remove box-shadow */ -.slider-track .slider-handle.custom { - box-shadow: none; - margin-left: -8px; -} - -/* for custom handle add text-shadow */ -.slider-track .slider-handle.custom::before { - text-shadow: 0 1px 2px rgba(0,0,0,.05); - color: #337ab7; - font-size: 26px; -} - -/* we make each tick a bit more clear */ -.slider .slider-tick { - background-image: -webkit-linear-gradient(top, #e6e6e6 0, #dedede 100%); - background-image: -o-linear-gradient(top, #e6e6e6 0, #dedede 100%); - background-image: linear-gradient(to bottom, #e6e6e6 0, #dedede 100%); -} - -.slider .slider-tick.in-selection { - background-image: -webkit-linear-gradient(top, #89cdef 0, #81bfde 100%); - background-image: -o-linear-gradient(top, #89cdef 0, #81bfde 100%); - background-image: linear-gradient(to bottom, #89cdef 0, #81bfde 100%); -} - -/* horizontal - triangle border-bottom color */ -.slider.slider-horizontal .slider-tick.triangle { - border-bottom-color: #dedede; -} -.slider.slider-horizontal .slider-handle.triangle { - border-bottom-color: #0480be; -} -.slider.slider-horizontal .slider-tick.triangle.in-selection { - border-bottom-color: #81bfde; -} - -/* vertical - triangle border-left color */ -.slider.slider-vertical .slider-tick.triangle { - border-left-color: #dedede; -} -.slider.slider-vertical .slider-handle.triangle { - border-left-color: #0480be; -} -.slider.slider-vertical .slider-tick.triangle.in-selection { - border-left-color: #81bfde; -} - -.slider.slider-horizontal { - width: 400px; - max-width: 100%; -} - -@media only screen and (max-width: 767px) { - .slider.slider-horizontal { - width: 100%; - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider.css b/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider.css deleted file mode 100644 index aa763b6bb6..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/slider/bootstrap-slider.css +++ /dev/null @@ -1,255 +0,0 @@ -/*! ======================================================= - VERSION 5.2.6 -========================================================= */ -/*! ========================================================= - * bootstrap-slider.js - * - * Maintainers: - * Kyle Kemp - * - Twitter: @seiyria - * - Github: seiyria - * Rohit Kalkur - * - Twitter: @Rovolutionary - * - Github: rovolution - * - * ========================================================= - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ -.slider { - display: inline-block; - vertical-align: middle; - position: relative; -} -.slider.slider-horizontal { - width: 210px; - height: 20px; -} -.slider.slider-horizontal .slider-track { - height: 10px; - width: 100%; - margin-top: -5px; - top: 50%; - left: 0; -} -.slider.slider-horizontal .slider-selection, -.slider.slider-horizontal .slider-track-low, -.slider.slider-horizontal .slider-track-high { - height: 100%; - top: 0; - bottom: 0; -} -.slider.slider-horizontal .slider-tick, -.slider.slider-horizontal .slider-handle { - margin-left: -10px; - margin-top: -5px; -} -.slider.slider-horizontal .slider-tick.triangle, -.slider.slider-horizontal .slider-handle.triangle { - border-width: 0 10px 10px 10px; - width: 0; - height: 0; - border-bottom-color: #0480be; - margin-top: 0; -} -.slider.slider-horizontal .slider-tick-label-container { - white-space: nowrap; - margin-top: 20px; -} -.slider.slider-horizontal .slider-tick-label-container .slider-tick-label { - padding-top: 4px; - display: inline-block; - text-align: center; -} -.slider.slider-vertical { - height: 210px; - width: 20px; -} -.slider.slider-vertical .slider-track { - width: 10px; - height: 100%; - margin-left: -5px; - left: 50%; - top: 0; -} -.slider.slider-vertical .slider-selection { - width: 100%; - left: 0; - top: 0; - bottom: 0; -} -.slider.slider-vertical .slider-track-low, -.slider.slider-vertical .slider-track-high { - width: 100%; - left: 0; - right: 0; -} -.slider.slider-vertical .slider-tick, -.slider.slider-vertical .slider-handle { - margin-left: -5px; - margin-top: -10px; -} -.slider.slider-vertical .slider-tick.triangle, -.slider.slider-vertical .slider-handle.triangle { - border-width: 10px 0 10px 10px; - width: 1px; - height: 1px; - border-left-color: #0480be; - margin-left: 0; -} -.slider.slider-vertical .slider-tick-label-container { - white-space: nowrap; -} -.slider.slider-vertical .slider-tick-label-container .slider-tick-label { - padding-left: 4px; -} -.slider.slider-disabled .slider-handle { - background-image: -webkit-linear-gradient(top, #dfdfdf 0%, #bebebe 100%); - background-image: -o-linear-gradient(top, #dfdfdf 0%, #bebebe 100%); - background-image: linear-gradient(to bottom, #dfdfdf 0%, #bebebe 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf', endColorstr='#ffbebebe', GradientType=0); -} -.slider.slider-disabled .slider-track { - background-image: -webkit-linear-gradient(top, #e5e5e5 0%, #e9e9e9 100%); - background-image: -o-linear-gradient(top, #e5e5e5 0%, #e9e9e9 100%); - background-image: linear-gradient(to bottom, #e5e5e5 0%, #e9e9e9 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5', endColorstr='#ffe9e9e9', GradientType=0); - cursor: not-allowed; -} -.slider input { - display: none; -} -.slider .tooltip.top { - margin-top: -36px; -} -.slider .tooltip-inner { - white-space: nowrap; -} -.slider .hide { - display: none; -} -.slider-track { - position: absolute; - cursor: pointer; - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #f9f9f9 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #f9f9f9 100%); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #f9f9f9 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - border-radius: 4px; -} -.slider-selection { - position: absolute; - background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; -} -.slider-selection.tick-slider-selection { - background-image: -webkit-linear-gradient(top, #89cdef 0%, #81bfde 100%); - background-image: -o-linear-gradient(top, #89cdef 0%, #81bfde 100%); - background-image: linear-gradient(to bottom, #89cdef 0%, #81bfde 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef', endColorstr='#ff81bfde', GradientType=0); -} -.slider-track-low, -.slider-track-high { - position: absolute; - background: transparent; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; -} -.slider-handle { - position: absolute; - width: 20px; - height: 20px; - background-color: #337ab7; - background-image: -webkit-linear-gradient(top, #149bdf 0%, #0480be 100%); - background-image: -o-linear-gradient(top, #149bdf 0%, #0480be 100%); - background-image: linear-gradient(to bottom, #149bdf 0%, #0480be 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - filter: none; - -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - border: 0px solid transparent; -} -.slider-handle.round { - border-radius: 50%; -} -.slider-handle.triangle { - background: transparent none; -} -.slider-handle.custom { - background: transparent none; -} -.slider-handle.custom::before { - line-height: 20px; - font-size: 20px; - content: '\2605'; - color: #726204; -} -.slider-tick { - position: absolute; - width: 20px; - height: 20px; - background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #f9f9f9 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #f9f9f9 0%, #f5f5f5 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - filter: none; - opacity: 0.8; - border: 0px solid transparent; -} -.slider-tick.round { - border-radius: 50%; -} -.slider-tick.triangle { - background: transparent none; -} -.slider-tick.custom { - background: transparent none; -} -.slider-tick.custom::before { - line-height: 20px; - font-size: 20px; - content: '\2605'; - color: #726204; -} -.slider-tick.in-selection { - background-image: -webkit-linear-gradient(top, #89cdef 0%, #81bfde 100%); - background-image: -o-linear-gradient(top, #89cdef 0%, #81bfde 100%); - background-image: linear-gradient(to bottom, #89cdef 0%, #81bfde 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef', endColorstr='#ff81bfde', GradientType=0); - opacity: 1; -} diff --git a/src/Umbraco.Web.UI.Client/lib/slider/js/bootstrap-slider.js b/src/Umbraco.Web.UI.Client/lib/slider/js/bootstrap-slider.js deleted file mode 100644 index 3ae97f4fd6..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/slider/js/bootstrap-slider.js +++ /dev/null @@ -1,1553 +0,0 @@ -/*! ======================================================= - VERSION 5.2.6 -========================================================= */ -/*! ========================================================= - * bootstrap-slider.js - * - * Maintainers: - * Kyle Kemp - * - Twitter: @seiyria - * - Github: seiyria - * Rohit Kalkur - * - Twitter: @Rovolutionary - * - Github: rovolution - * - * ========================================================= - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - - -/** - * Bridget makes jQuery widgets - * v1.0.1 - * MIT license - */ - -(function(root, factory) { - if(typeof define === "function" && define.amd) { - define(["jquery"], factory); - } - else if(typeof module === "object" && module.exports) { - var jQuery; - try { - jQuery = require("jquery"); - } - catch (err) { - jQuery = null; - } - module.exports = factory(jQuery); - } - else { - root.Slider = factory(root.jQuery); - } -}(this, function($) { - // Reference to Slider constructor - var Slider; - - - (function( $ ) { - - 'use strict'; - - // -------------------------- utils -------------------------- // - - var slice = Array.prototype.slice; - - function noop() {} - - // -------------------------- definition -------------------------- // - - function defineBridget( $ ) { - - // bail if no jQuery - if ( !$ ) { - return; - } - - // -------------------------- addOptionMethod -------------------------- // - - /** - * adds option method -> $().plugin('option', {...}) - * @param {Function} PluginClass - constructor class - */ - function addOptionMethod( PluginClass ) { - // don't overwrite original option method - if ( PluginClass.prototype.option ) { - return; - } - - // option setter - PluginClass.prototype.option = function( opts ) { - // bail out if not an object - if ( !$.isPlainObject( opts ) ){ - return; - } - this.options = $.extend( true, this.options, opts ); - }; - } - - - // -------------------------- plugin bridge -------------------------- // - - // helper function for logging errors - // $.error breaks jQuery chaining - var logError = typeof console === 'undefined' ? noop : - function( message ) { - console.error( message ); - }; - - /** - * jQuery plugin bridge, access methods like $elem.plugin('method') - * @param {String} namespace - plugin name - * @param {Function} PluginClass - constructor class - */ - function bridge( namespace, PluginClass ) { - // add to jQuery fn namespace - $.fn[ namespace ] = function( options ) { - if ( typeof options === 'string' ) { - // call plugin method when first argument is a string - // get arguments for method - var args = slice.call( arguments, 1 ); - - for ( var i=0, len = this.length; i < len; i++ ) { - var elem = this[i]; - var instance = $.data( elem, namespace ); - if ( !instance ) { - logError( "cannot call methods on " + namespace + " prior to initialization; " + - "attempted to call '" + options + "'" ); - continue; - } - if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { - logError( "no such method '" + options + "' for " + namespace + " instance" ); - continue; - } - - // trigger method with arguments - var returnValue = instance[ options ].apply( instance, args); - - // break look and return first value if provided - if ( returnValue !== undefined && returnValue !== instance) { - return returnValue; - } - } - // return this if no return value - return this; - } else { - var objects = this.map( function() { - var instance = $.data( this, namespace ); - if ( instance ) { - // apply options & init - instance.option( options ); - instance._init(); - } else { - // initialize new instance - instance = new PluginClass( this, options ); - $.data( this, namespace, instance ); - } - return $(this); - }); - - if(!objects || objects.length > 1) { - return objects; - } else { - return objects[0]; - } - } - }; - - } - - // -------------------------- bridget -------------------------- // - - /** - * converts a Prototypical class into a proper jQuery plugin - * the class must have a ._init method - * @param {String} namespace - plugin name, used in $().pluginName - * @param {Function} PluginClass - constructor class - */ - $.bridget = function( namespace, PluginClass ) { - addOptionMethod( PluginClass ); - bridge( namespace, PluginClass ); - }; - - return $.bridget; - - } - - // get jquery from browser global - defineBridget( $ ); - - })( $ ); - - - /************************************************* - - BOOTSTRAP-SLIDER SOURCE CODE - - **************************************************/ - - (function($) { - - var ErrorMsgs = { - formatInvalidInputErrorMsg : function(input) { - return "Invalid input value '" + input + "' passed in"; - }, - callingContextNotSliderInstance : "Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method" - }; - - var SliderScale = { - linear: { - toValue: function(percentage) { - var rawValue = percentage/100 * (this.options.max - this.options.min); - if (this.options.ticks_positions.length > 0) { - var minv, maxv, minp, maxp = 0; - for (var i = 0; i < this.options.ticks_positions.length; i++) { - if (percentage <= this.options.ticks_positions[i]) { - minv = (i > 0) ? this.options.ticks[i-1] : 0; - minp = (i > 0) ? this.options.ticks_positions[i-1] : 0; - maxv = this.options.ticks[i]; - maxp = this.options.ticks_positions[i]; - - break; - } - } - if (i > 0) { - var partialPercentage = (percentage - minp) / (maxp - minp); - rawValue = minv + partialPercentage * (maxv - minv); - } - } - - var value = this.options.min + Math.round(rawValue / this.options.step) * this.options.step; - if (value < this.options.min) { - return this.options.min; - } else if (value > this.options.max) { - return this.options.max; - } else { - return value; - } - }, - toPercentage: function(value) { - if (this.options.max === this.options.min) { - return 0; - } - - if (this.options.ticks_positions.length > 0) { - var minv, maxv, minp, maxp = 0; - for (var i = 0; i < this.options.ticks.length; i++) { - if (value <= this.options.ticks[i]) { - minv = (i > 0) ? this.options.ticks[i-1] : 0; - minp = (i > 0) ? this.options.ticks_positions[i-1] : 0; - maxv = this.options.ticks[i]; - maxp = this.options.ticks_positions[i]; - - break; - } - } - if (i > 0) { - var partialPercentage = (value - minv) / (maxv - minv); - return minp + partialPercentage * (maxp - minp); - } - } - - return 100 * (value - this.options.min) / (this.options.max - this.options.min); - } - }, - - logarithmic: { - /* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */ - toValue: function(percentage) { - var min = (this.options.min === 0) ? 0 : Math.log(this.options.min); - var max = Math.log(this.options.max); - var value = Math.exp(min + (max - min) * percentage / 100); - value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step; - /* Rounding to the nearest step could exceed the min or - * max, so clip to those values. */ - if (value < this.options.min) { - return this.options.min; - } else if (value > this.options.max) { - return this.options.max; - } else { - return value; - } - }, - toPercentage: function(value) { - if (this.options.max === this.options.min) { - return 0; - } else { - var max = Math.log(this.options.max); - var min = this.options.min === 0 ? 0 : Math.log(this.options.min); - var v = value === 0 ? 0 : Math.log(value); - return 100 * (v - min) / (max - min); - } - } - } - }; - - - /************************************************* - - CONSTRUCTOR - - **************************************************/ - Slider = function(element, options) { - createNewSlider.call(this, element, options); - return this; - }; - - function createNewSlider(element, options) { - - /* - The internal state object is used to store data about the current 'state' of slider. - - This includes values such as the `value`, `enabled`, etc... - */ - this._state = { - value: null, - enabled: null, - offset: null, - size: null, - percentage: null, - inDrag: false, - over: false - }; - - - if(typeof element === "string") { - this.element = document.querySelector(element); - } else if(element instanceof HTMLElement) { - this.element = element; - } - - /************************************************* - - Process Options - - **************************************************/ - options = options ? options : {}; - var optionTypes = Object.keys(this.defaultOptions); - - for(var i = 0; i < optionTypes.length; i++) { - var optName = optionTypes[i]; - - // First check if an option was passed in via the constructor - var val = options[optName]; - // If no data attrib, then check data atrributes - val = (typeof val !== 'undefined') ? val : getDataAttrib(this.element, optName); - // Finally, if nothing was specified, use the defaults - val = (val !== null) ? val : this.defaultOptions[optName]; - - // Set all options on the instance of the Slider - if(!this.options) { - this.options = {}; - } - this.options[optName] = val; - } - - /* - Validate `tooltip_position` against 'orientation` - - if `tooltip_position` is incompatible with orientation, swith it to a default compatible with specified `orientation` - -- default for "vertical" -> "right" - -- default for "horizontal" -> "left" - */ - if(this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) { - - this.options.tooltip_position = "right"; - - } - else if(this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) { - - this.options.tooltip_position = "top"; - - } - - function getDataAttrib(element, optName) { - var dataName = "data-slider-" + optName.replace(/_/g, '-'); - var dataValString = element.getAttribute(dataName); - - try { - return JSON.parse(dataValString); - } - catch(err) { - return dataValString; - } - } - - /************************************************* - - Create Markup - - **************************************************/ - - var origWidth = this.element.style.width; - var updateSlider = false; - var parent = this.element.parentNode; - var sliderTrackSelection; - var sliderTrackLow, sliderTrackHigh; - var sliderMinHandle; - var sliderMaxHandle; - - if (this.sliderElem) { - updateSlider = true; - } else { - /* Create elements needed for slider */ - this.sliderElem = document.createElement("div"); - this.sliderElem.className = "slider"; - - /* Create slider track elements */ - var sliderTrack = document.createElement("div"); - sliderTrack.className = "slider-track"; - - sliderTrackLow = document.createElement("div"); - sliderTrackLow.className = "slider-track-low"; - - sliderTrackSelection = document.createElement("div"); - sliderTrackSelection.className = "slider-selection"; - - sliderTrackHigh = document.createElement("div"); - sliderTrackHigh.className = "slider-track-high"; - - sliderMinHandle = document.createElement("div"); - sliderMinHandle.className = "slider-handle min-slider-handle"; - - sliderMaxHandle = document.createElement("div"); - sliderMaxHandle.className = "slider-handle max-slider-handle"; - - sliderTrack.appendChild(sliderTrackLow); - sliderTrack.appendChild(sliderTrackSelection); - sliderTrack.appendChild(sliderTrackHigh); - - /* Create ticks */ - this.ticks = []; - if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { - for (i = 0; i < this.options.ticks.length; i++) { - var tick = document.createElement('div'); - tick.className = 'slider-tick'; - - this.ticks.push(tick); - sliderTrack.appendChild(tick); - } - - sliderTrackSelection.className += " tick-slider-selection"; - } - - sliderTrack.appendChild(sliderMinHandle); - sliderTrack.appendChild(sliderMaxHandle); - - this.tickLabels = []; - if (Array.isArray(this.options.ticks_labels) && this.options.ticks_labels.length > 0) { - this.tickLabelContainer = document.createElement('div'); - this.tickLabelContainer.className = 'slider-tick-label-container'; - - for (i = 0; i < this.options.ticks_labels.length; i++) { - var label = document.createElement('div'); - var noTickPositionsSpecified = this.options.ticks_positions.length === 0; - var tickLabelsIndex = (this.options.reversed && noTickPositionsSpecified) ? (this.options.ticks_labels.length - (i + 1)) : i; - label.className = 'slider-tick-label'; - label.innerHTML = this.options.ticks_labels[tickLabelsIndex]; - - this.tickLabels.push(label); - this.tickLabelContainer.appendChild(label); - } - } - - - var createAndAppendTooltipSubElements = function(tooltipElem) { - var arrow = document.createElement("div"); - arrow.className = "tooltip-arrow"; - - var inner = document.createElement("div"); - inner.className = "tooltip-inner"; - - tooltipElem.appendChild(arrow); - tooltipElem.appendChild(inner); - - }; - - /* Create tooltip elements */ - var sliderTooltip = document.createElement("div"); - sliderTooltip.className = "tooltip tooltip-main"; - createAndAppendTooltipSubElements(sliderTooltip); - - var sliderTooltipMin = document.createElement("div"); - sliderTooltipMin.className = "tooltip tooltip-min"; - createAndAppendTooltipSubElements(sliderTooltipMin); - - var sliderTooltipMax = document.createElement("div"); - sliderTooltipMax.className = "tooltip tooltip-max"; - createAndAppendTooltipSubElements(sliderTooltipMax); - - - /* Append components to sliderElem */ - this.sliderElem.appendChild(sliderTrack); - this.sliderElem.appendChild(sliderTooltip); - this.sliderElem.appendChild(sliderTooltipMin); - this.sliderElem.appendChild(sliderTooltipMax); - - if (this.tickLabelContainer) { - this.sliderElem.appendChild(this.tickLabelContainer); - } - - /* Append slider element to parent container, right before the original element */ - parent.insertBefore(this.sliderElem, this.element); - - /* Hide original element */ - this.element.style.display = "none"; - } - /* If JQuery exists, cache JQ references */ - if($) { - this.$element = $(this.element); - this.$sliderElem = $(this.sliderElem); - } - - /************************************************* - - Setup - - **************************************************/ - this.eventToCallbackMap = {}; - this.sliderElem.id = this.options.id; - - this.touchCapable = 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch); - - this.tooltip = this.sliderElem.querySelector('.tooltip-main'); - this.tooltipInner = this.tooltip.querySelector('.tooltip-inner'); - - this.tooltip_min = this.sliderElem.querySelector('.tooltip-min'); - this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner'); - - this.tooltip_max = this.sliderElem.querySelector('.tooltip-max'); - this.tooltipInner_max= this.tooltip_max.querySelector('.tooltip-inner'); - - if (SliderScale[this.options.scale]) { - this.options.scale = SliderScale[this.options.scale]; - } - - if (updateSlider === true) { - // Reset classes - this._removeClass(this.sliderElem, 'slider-horizontal'); - this._removeClass(this.sliderElem, 'slider-vertical'); - this._removeClass(this.tooltip, 'hide'); - this._removeClass(this.tooltip_min, 'hide'); - this._removeClass(this.tooltip_max, 'hide'); - - // Undo existing inline styles for track - ["left", "top", "width", "height"].forEach(function(prop) { - this._removeProperty(this.trackLow, prop); - this._removeProperty(this.trackSelection, prop); - this._removeProperty(this.trackHigh, prop); - }, this); - - // Undo inline styles on handles - [this.handle1, this.handle2].forEach(function(handle) { - this._removeProperty(handle, 'left'); - this._removeProperty(handle, 'top'); - }, this); - - // Undo inline styles and classes on tooltips - [this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function(tooltip) { - this._removeProperty(tooltip, 'left'); - this._removeProperty(tooltip, 'top'); - this._removeProperty(tooltip, 'margin-left'); - this._removeProperty(tooltip, 'margin-top'); - - this._removeClass(tooltip, 'right'); - this._removeClass(tooltip, 'top'); - }, this); - } - - if(this.options.orientation === 'vertical') { - this._addClass(this.sliderElem,'slider-vertical'); - this.stylePos = 'top'; - this.mousePos = 'pageY'; - this.sizePos = 'offsetHeight'; - } else { - this._addClass(this.sliderElem, 'slider-horizontal'); - this.sliderElem.style.width = origWidth; - this.options.orientation = 'horizontal'; - this.stylePos = 'left'; - this.mousePos = 'pageX'; - this.sizePos = 'offsetWidth'; - - } - this._setTooltipPosition(); - /* In case ticks are specified, overwrite the min and max bounds */ - if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { - this.options.max = Math.max.apply(Math, this.options.ticks); - this.options.min = Math.min.apply(Math, this.options.ticks); - } - - if (Array.isArray(this.options.value)) { - this.options.range = true; - this._state.value = this.options.value; - } - else if (this.options.range) { - // User wants a range, but value is not an array - this._state.value = [this.options.value, this.options.max]; - } - else { - this._state.value = this.options.value; - } - - this.trackLow = sliderTrackLow || this.trackLow; - this.trackSelection = sliderTrackSelection || this.trackSelection; - this.trackHigh = sliderTrackHigh || this.trackHigh; - - if (this.options.selection === 'none') { - this._addClass(this.trackLow, 'hide'); - this._addClass(this.trackSelection, 'hide'); - this._addClass(this.trackHigh, 'hide'); - } - - this.handle1 = sliderMinHandle || this.handle1; - this.handle2 = sliderMaxHandle || this.handle2; - - if (updateSlider === true) { - // Reset classes - this._removeClass(this.handle1, 'round triangle'); - this._removeClass(this.handle2, 'round triangle hide'); - - for (i = 0; i < this.ticks.length; i++) { - this._removeClass(this.ticks[i], 'round triangle hide'); - } - } - - var availableHandleModifiers = ['round', 'triangle', 'custom']; - var isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1; - if (isValidHandleType) { - this._addClass(this.handle1, this.options.handle); - this._addClass(this.handle2, this.options.handle); - - for (i = 0; i < this.ticks.length; i++) { - this._addClass(this.ticks[i], this.options.handle); - } - } - - this._state.offset = this._offset(this.sliderElem); - this._state.size = this.sliderElem[this.sizePos]; - this.setValue(this._state.value); - - /****************************************** - - Bind Event Listeners - - ******************************************/ - - // Bind keyboard handlers - this.handle1Keydown = this._keydown.bind(this, 0); - this.handle1.addEventListener("keydown", this.handle1Keydown, false); - - this.handle2Keydown = this._keydown.bind(this, 1); - this.handle2.addEventListener("keydown", this.handle2Keydown, false); - - this.mousedown = this._mousedown.bind(this); - if (this.touchCapable) { - // Bind touch handlers - this.sliderElem.addEventListener("touchstart", this.mousedown, false); - } - this.sliderElem.addEventListener("mousedown", this.mousedown, false); - - - // Bind tooltip-related handlers - if(this.options.tooltip === 'hide') { - this._addClass(this.tooltip, 'hide'); - this._addClass(this.tooltip_min, 'hide'); - this._addClass(this.tooltip_max, 'hide'); - } - else if(this.options.tooltip === 'always') { - this._showTooltip(); - this._alwaysShowTooltip = true; - } - else { - this.showTooltip = this._showTooltip.bind(this); - this.hideTooltip = this._hideTooltip.bind(this); - - this.sliderElem.addEventListener("mouseenter", this.showTooltip, false); - this.sliderElem.addEventListener("mouseleave", this.hideTooltip, false); - - this.handle1.addEventListener("focus", this.showTooltip, false); - this.handle1.addEventListener("blur", this.hideTooltip, false); - - this.handle2.addEventListener("focus", this.showTooltip, false); - this.handle2.addEventListener("blur", this.hideTooltip, false); - } - - if(this.options.enabled) { - this.enable(); - } else { - this.disable(); - } - } - - - - /************************************************* - - INSTANCE PROPERTIES/METHODS - - - Any methods bound to the prototype are considered - part of the plugin's `public` interface - - **************************************************/ - Slider.prototype = { - _init: function() {}, // NOTE: Must exist to support bridget - - constructor: Slider, - - defaultOptions: { - id: "", - min: 0, - max: 10, - step: 1, - precision: 0, - orientation: 'horizontal', - value: 5, - range: false, - selection: 'before', - tooltip: 'show', - tooltip_split: false, - handle: 'round', - reversed: false, - enabled: true, - formatter: function(val) { - if (Array.isArray(val)) { - return val[0] + " : " + val[1]; - } else { - return val; - } - }, - natural_arrow_keys: false, - ticks: [], - ticks_positions: [], - ticks_labels: [], - ticks_snap_bounds: 0, - scale: 'linear', - focus: false, - tooltip_position: null - }, - - getElement: function() { - return this.sliderElem; - }, - - getValue: function() { - if (this.options.range) { - return this._state.value; - } - else { - return this._state.value[0]; - } - }, - - setValue: function(val, triggerSlideEvent, triggerChangeEvent) { - if (!val) { - val = 0; - } - var oldValue = this.getValue(); - this._state.value = this._validateInputValue(val); - var applyPrecision = this._applyPrecision.bind(this); - - if (this.options.range) { - this._state.value[0] = applyPrecision(this._state.value[0]); - this._state.value[1] = applyPrecision(this._state.value[1]); - - this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0])); - this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1])); - } - else { - this._state.value = applyPrecision(this._state.value); - this._state.value = [ Math.max(this.options.min, Math.min(this.options.max, this._state.value))]; - this._addClass(this.handle2, 'hide'); - if (this.options.selection === 'after') { - this._state.value[1] = this.options.max; - } else { - this._state.value[1] = this.options.min; - } - } - - if (this.options.max > this.options.min) { - this._state.percentage = [ - this._toPercentage(this._state.value[0]), - this._toPercentage(this._state.value[1]), - this.options.step * 100 / (this.options.max - this.options.min) - ]; - } else { - this._state.percentage = [0, 0, 100]; - } - - this._layout(); - var newValue = this.options.range ? this._state.value : this._state.value[0]; - - if(triggerSlideEvent === true) { - this._trigger('slide', newValue); - } - if( (oldValue !== newValue) && (triggerChangeEvent === true) ) { - this._trigger('change', { - oldValue: oldValue, - newValue: newValue - }); - } - this._setDataVal(newValue); - - return this; - }, - - destroy: function(){ - // Remove event handlers on slider elements - this._removeSliderEventHandlers(); - - // Remove the slider from the DOM - this.sliderElem.parentNode.removeChild(this.sliderElem); - /* Show original element */ - this.element.style.display = ""; - - // Clear out custom event bindings - this._cleanUpEventCallbacksMap(); - - // Remove data values - this.element.removeAttribute("data"); - - // Remove JQuery handlers/data - if($) { - this._unbindJQueryEventHandlers(); - this.$element.removeData('slider'); - } - }, - - disable: function() { - this._state.enabled = false; - this.handle1.removeAttribute("tabindex"); - this.handle2.removeAttribute("tabindex"); - this._addClass(this.sliderElem, 'slider-disabled'); - this._trigger('slideDisabled'); - - return this; - }, - - enable: function() { - this._state.enabled = true; - this.handle1.setAttribute("tabindex", 0); - this.handle2.setAttribute("tabindex", 0); - this._removeClass(this.sliderElem, 'slider-disabled'); - this._trigger('slideEnabled'); - - return this; - }, - - toggle: function() { - if(this._state.enabled) { - this.disable(); - } else { - this.enable(); - } - return this; - }, - - isEnabled: function() { - return this._state.enabled; - }, - - on: function(evt, callback) { - this._bindNonQueryEventHandler(evt, callback); - return this; - }, - - off: function(evt, callback) { - if($) { - this.$element.off(evt, callback); - this.$sliderElem.off(evt, callback); - } else { - this._unbindNonQueryEventHandler(evt, callback); - } - }, - - getAttribute: function(attribute) { - if(attribute) { - return this.options[attribute]; - } else { - return this.options; - } - }, - - setAttribute: function(attribute, value) { - this.options[attribute] = value; - return this; - }, - - refresh: function() { - this._removeSliderEventHandlers(); - createNewSlider.call(this, this.element, this.options); - if($) { - // Bind new instance of slider to the element - $.data(this.element, 'slider', this); - } - return this; - }, - - relayout: function() { - this._layout(); - return this; - }, - - /******************************+ - - HELPERS - - - Any method that is not part of the public interface. - - Place it underneath this comment block and write its signature like so: - - _fnName : function() {...} - - ********************************/ - _removeSliderEventHandlers: function() { - // Remove keydown event listeners - this.handle1.removeEventListener("keydown", this.handle1Keydown, false); - this.handle2.removeEventListener("keydown", this.handle2Keydown, false); - - if (this.showTooltip) { - this.handle1.removeEventListener("focus", this.showTooltip, false); - this.handle2.removeEventListener("focus", this.showTooltip, false); - } - if (this.hideTooltip) { - this.handle1.removeEventListener("blur", this.hideTooltip, false); - this.handle2.removeEventListener("blur", this.hideTooltip, false); - } - - // Remove event listeners from sliderElem - if (this.showTooltip) { - this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false); - } - if (this.hideTooltip) { - this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false); - } - this.sliderElem.removeEventListener("touchstart", this.mousedown, false); - this.sliderElem.removeEventListener("mousedown", this.mousedown, false); - }, - _bindNonQueryEventHandler: function(evt, callback) { - if(this.eventToCallbackMap[evt] === undefined) { - this.eventToCallbackMap[evt] = []; - } - this.eventToCallbackMap[evt].push(callback); - }, - _unbindNonQueryEventHandler: function(evt, callback) { - var callbacks = this.eventToCallbackMap[evt]; - if(callbacks !== undefined) { - for (var i = 0; i < callbacks.length; i++) { - if (callbacks[i] === callback) { - callbacks.splice(i, 1); - break; - } - } - } - }, - _cleanUpEventCallbacksMap: function() { - var eventNames = Object.keys(this.eventToCallbackMap); - for(var i = 0; i < eventNames.length; i++) { - var eventName = eventNames[i]; - this.eventToCallbackMap[eventName] = null; - } - }, - _showTooltip: function() { - if (this.options.tooltip_split === false ){ - this._addClass(this.tooltip, 'in'); - this.tooltip_min.style.display = 'none'; - this.tooltip_max.style.display = 'none'; - } else { - this._addClass(this.tooltip_min, 'in'); - this._addClass(this.tooltip_max, 'in'); - this.tooltip.style.display = 'none'; - } - this._state.over = true; - }, - _hideTooltip: function() { - if (this._state.inDrag === false && this.alwaysShowTooltip !== true) { - this._removeClass(this.tooltip, 'in'); - this._removeClass(this.tooltip_min, 'in'); - this._removeClass(this.tooltip_max, 'in'); - } - this._state.over = false; - }, - _layout: function() { - var positionPercentages; - - if(this.options.reversed) { - positionPercentages = [ 100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]]; - } - else { - positionPercentages = [ this._state.percentage[0], this._state.percentage[1] ]; - } - - this.handle1.style[this.stylePos] = positionPercentages[0]+'%'; - this.handle2.style[this.stylePos] = positionPercentages[1]+'%'; - - /* Position ticks and labels */ - if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { - - var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width'; - var styleMargin = this.options.orientation === 'vertical' ? 'marginTop' : 'marginLeft'; - var labelSize = this._state.size / (this.options.ticks.length - 1); - - if (this.tickLabelContainer) { - var extraMargin = 0; - if (this.options.ticks_positions.length === 0) { - if (this.options.orientation !== 'vertical') { - this.tickLabelContainer.style[styleMargin] = -labelSize/2 + 'px'; - } - - extraMargin = this.tickLabelContainer.offsetHeight; - } else { - /* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */ - for (i = 0 ; i < this.tickLabelContainer.childNodes.length; i++) { - if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) { - extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight; - } - } - } - if (this.options.orientation === 'horizontal') { - this.sliderElem.style.marginBottom = extraMargin + 'px'; - } - } - for (var i = 0; i < this.options.ticks.length; i++) { - - var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]); - - if (this.options.reversed) { - percentage = 100 - percentage; - } - - this.ticks[i].style[this.stylePos] = percentage + '%'; - - /* Set class labels to denote whether ticks are in the selection */ - this._removeClass(this.ticks[i], 'in-selection'); - if (!this.options.range) { - if (this.options.selection === 'after' && percentage >= positionPercentages[0]){ - this._addClass(this.ticks[i], 'in-selection'); - } else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) { - this._addClass(this.ticks[i], 'in-selection'); - } - } else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) { - this._addClass(this.ticks[i], 'in-selection'); - } - - if (this.tickLabels[i]) { - this.tickLabels[i].style[styleSize] = labelSize + 'px'; - - if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) { - this.tickLabels[i].style.position = 'absolute'; - this.tickLabels[i].style[this.stylePos] = percentage + '%'; - this.tickLabels[i].style[styleMargin] = -labelSize/2 + 'px'; - } else if (this.options.orientation === 'vertical') { - this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + 'px'; - this.tickLabelContainer.style['marginTop'] = this.sliderElem.offsetWidth / 2 * -1 + 'px'; - } - } - } - } - - var formattedTooltipVal; - - if (this.options.range) { - formattedTooltipVal = this.options.formatter(this._state.value); - this._setText(this.tooltipInner, formattedTooltipVal); - this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0])/2 + '%'; - - if (this.options.orientation === 'vertical') { - this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); - } else { - this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); - } - - if (this.options.orientation === 'vertical') { - this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); - } else { - this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); - } - - var innerTooltipMinText = this.options.formatter(this._state.value[0]); - this._setText(this.tooltipInner_min, innerTooltipMinText); - - var innerTooltipMaxText = this.options.formatter(this._state.value[1]); - this._setText(this.tooltipInner_max, innerTooltipMaxText); - - this.tooltip_min.style[this.stylePos] = positionPercentages[0] + '%'; - - if (this.options.orientation === 'vertical') { - this._css(this.tooltip_min, 'margin-top', -this.tooltip_min.offsetHeight / 2 + 'px'); - } else { - this._css(this.tooltip_min, 'margin-left', -this.tooltip_min.offsetWidth / 2 + 'px'); - } - - this.tooltip_max.style[this.stylePos] = positionPercentages[1] + '%'; - - if (this.options.orientation === 'vertical') { - this._css(this.tooltip_max, 'margin-top', -this.tooltip_max.offsetHeight / 2 + 'px'); - } else { - this._css(this.tooltip_max, 'margin-left', -this.tooltip_max.offsetWidth / 2 + 'px'); - } - } else { - formattedTooltipVal = this.options.formatter(this._state.value[0]); - this._setText(this.tooltipInner, formattedTooltipVal); - - this.tooltip.style[this.stylePos] = positionPercentages[0] + '%'; - if (this.options.orientation === 'vertical') { - this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px'); - } else { - this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px'); - } - } - - if (this.options.orientation === 'vertical') { - this.trackLow.style.top = '0'; - this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; - - this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; - this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%'; - - this.trackHigh.style.bottom = '0'; - this.trackHigh.style.height = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%'; - } - else { - this.trackLow.style.left = '0'; - this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; - - this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) +'%'; - this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%'; - - this.trackHigh.style.right = '0'; - this.trackHigh.style.width = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%'; - - var offset_min = this.tooltip_min.getBoundingClientRect(); - var offset_max = this.tooltip_max.getBoundingClientRect(); - - if (offset_min.right > offset_max.left) { - this._removeClass(this.tooltip_max, 'top'); - this._addClass(this.tooltip_max, 'bottom'); - this.tooltip_max.style.top = 18 + 'px'; - } else { - this._removeClass(this.tooltip_max, 'bottom'); - this._addClass(this.tooltip_max, 'top'); - this.tooltip_max.style.top = this.tooltip_min.style.top; - } - } - }, - _removeProperty: function(element, prop) { - if (element.style.removeProperty) { - element.style.removeProperty(prop); - } else { - element.style.removeAttribute(prop); - } - }, - _mousedown: function(ev) { - if(!this._state.enabled) { - return false; - } - - this._state.offset = this._offset(this.sliderElem); - this._state.size = this.sliderElem[this.sizePos]; - - var percentage = this._getPercentage(ev); - - if (this.options.range) { - var diff1 = Math.abs(this._state.percentage[0] - percentage); - var diff2 = Math.abs(this._state.percentage[1] - percentage); - this._state.dragged = (diff1 < diff2) ? 0 : 1; - } else { - this._state.dragged = 0; - } - - this._state.percentage[this._state.dragged] = percentage; - this._layout(); - - if (this.touchCapable) { - document.removeEventListener("touchmove", this.mousemove, false); - document.removeEventListener("touchend", this.mouseup, false); - } - - if(this.mousemove){ - document.removeEventListener("mousemove", this.mousemove, false); - } - if(this.mouseup){ - document.removeEventListener("mouseup", this.mouseup, false); - } - - this.mousemove = this._mousemove.bind(this); - this.mouseup = this._mouseup.bind(this); - - if (this.touchCapable) { - // Touch: Bind touch events: - document.addEventListener("touchmove", this.mousemove, false); - document.addEventListener("touchend", this.mouseup, false); - } - // Bind mouse events: - document.addEventListener("mousemove", this.mousemove, false); - document.addEventListener("mouseup", this.mouseup, false); - - this._state.inDrag = true; - var newValue = this._calculateValue(); - - this._trigger('slideStart', newValue); - - this._setDataVal(newValue); - this.setValue(newValue, false, true); - - this._pauseEvent(ev); - - if (this.options.focus) { - this._triggerFocusOnHandle(this._state.dragged); - } - - return true; - }, - _triggerFocusOnHandle: function(handleIdx) { - if(handleIdx === 0) { - this.handle1.focus(); - } - if(handleIdx === 1) { - this.handle2.focus(); - } - }, - _keydown: function(handleIdx, ev) { - if(!this._state.enabled) { - return false; - } - - var dir; - switch (ev.keyCode) { - case 37: // left - case 40: // down - dir = -1; - break; - case 39: // right - case 38: // up - dir = 1; - break; - } - if (!dir) { - return; - } - - // use natural arrow keys instead of from min to max - if (this.options.natural_arrow_keys) { - var ifVerticalAndNotReversed = (this.options.orientation === 'vertical' && !this.options.reversed); - var ifHorizontalAndReversed = (this.options.orientation === 'horizontal' && this.options.reversed); - - if (ifVerticalAndNotReversed || ifHorizontalAndReversed) { - dir = -dir; - } - } - - var val = this._state.value[handleIdx] + dir * this.options.step; - if (this.options.range) { - val = [ (!handleIdx) ? val : this._state.value[0], - ( handleIdx) ? val : this._state.value[1]]; - } - - this._trigger('slideStart', val); - this._setDataVal(val); - this.setValue(val, true, true); - - this._setDataVal(val); - this._trigger('slideStop', val); - this._layout(); - - this._pauseEvent(ev); - - return false; - }, - _pauseEvent: function(ev) { - if(ev.stopPropagation) { - ev.stopPropagation(); - } - if(ev.preventDefault) { - ev.preventDefault(); - } - ev.cancelBubble=true; - ev.returnValue=false; - }, - _mousemove: function(ev) { - if(!this._state.enabled) { - return false; - } - - var percentage = this._getPercentage(ev); - this._adjustPercentageForRangeSliders(percentage); - this._state.percentage[this._state.dragged] = percentage; - this._layout(); - - var val = this._calculateValue(true); - this.setValue(val, true, true); - - return false; - }, - _adjustPercentageForRangeSliders: function(percentage) { - if (this.options.range) { - var precision = this._getNumDigitsAfterDecimalPlace(percentage); - precision = precision ? precision - 1 : 0; - var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision); - if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) { - this._state.percentage[0] = this._state.percentage[1]; - this._state.dragged = 1; - } else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) { - this._state.percentage[1] = this._state.percentage[0]; - this._state.dragged = 0; - } - } - }, - _mouseup: function() { - if(!this._state.enabled) { - return false; - } - if (this.touchCapable) { - // Touch: Unbind touch event handlers: - document.removeEventListener("touchmove", this.mousemove, false); - document.removeEventListener("touchend", this.mouseup, false); - } - // Unbind mouse event handlers: - document.removeEventListener("mousemove", this.mousemove, false); - document.removeEventListener("mouseup", this.mouseup, false); - - this._state.inDrag = false; - if (this._state.over === false) { - this._hideTooltip(); - } - var val = this._calculateValue(true); - - this._layout(); - this._setDataVal(val); - this._trigger('slideStop', val); - - return false; - }, - _calculateValue: function(snapToClosestTick) { - var val; - if (this.options.range) { - val = [this.options.min,this.options.max]; - if (this._state.percentage[0] !== 0){ - val[0] = this._toValue(this._state.percentage[0]); - val[0] = this._applyPrecision(val[0]); - } - if (this._state.percentage[1] !== 100){ - val[1] = this._toValue(this._state.percentage[1]); - val[1] = this._applyPrecision(val[1]); - } - } else { - val = this._toValue(this._state.percentage[0]); - val = parseFloat(val); - val = this._applyPrecision(val); - } - - if (snapToClosestTick) { - var min = [val, Infinity]; - for (var i = 0; i < this.options.ticks.length; i++) { - var diff = Math.abs(this.options.ticks[i] - val); - if (diff <= min[1]) { - min = [this.options.ticks[i], diff]; - } - } - if (min[1] <= this.options.ticks_snap_bounds) { - return min[0]; - } - } - - return val; - }, - _applyPrecision: function(val) { - var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step); - return this._applyToFixedAndParseFloat(val, precision); - }, - _getNumDigitsAfterDecimalPlace: function(num) { - var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/); - if (!match) { return 0; } - return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)); - }, - _applyToFixedAndParseFloat: function(num, toFixedInput) { - var truncatedNum = num.toFixed(toFixedInput); - return parseFloat(truncatedNum); - }, - /* - Credits to Mike Samuel for the following method! - Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number - */ - _getPercentage: function(ev) { - if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) { - ev = ev.touches[0]; - } - - var eventPosition = ev[this.mousePos]; - var sliderOffset = this._state.offset[this.stylePos]; - var distanceToSlide = eventPosition - sliderOffset; - // Calculate what percent of the length the slider handle has slid - var percentage = (distanceToSlide / this._state.size) * 100; - percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2]; - if (this.options.reversed) { - percentage = 100 - percentage; - } - - // Make sure the percent is within the bounds of the slider. - // 0% corresponds to the 'min' value of the slide - // 100% corresponds to the 'max' value of the slide - return Math.max(0, Math.min(100, percentage)); - }, - _validateInputValue: function(val) { - if (typeof val === 'number') { - return val; - } else if (Array.isArray(val)) { - this._validateArray(val); - return val; - } else { - throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(val) ); - } - }, - _validateArray: function(val) { - for(var i = 0; i < val.length; i++) { - var input = val[i]; - if (typeof input !== 'number') { throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(input) ); } - } - }, - _setDataVal: function(val) { - this.element.setAttribute('data-value', val); - this.element.setAttribute('value', val); - this.element.value = val; - }, - _trigger: function(evt, val) { - val = (val || val === 0) ? val : undefined; - - var callbackFnArray = this.eventToCallbackMap[evt]; - if(callbackFnArray && callbackFnArray.length) { - for(var i = 0; i < callbackFnArray.length; i++) { - var callbackFn = callbackFnArray[i]; - callbackFn(val); - } - } - - /* If JQuery exists, trigger JQuery events */ - if($) { - this._triggerJQueryEvent(evt, val); - } - }, - _triggerJQueryEvent: function(evt, val) { - var eventData = { - type: evt, - value: val - }; - this.$element.trigger(eventData); - this.$sliderElem.trigger(eventData); - }, - _unbindJQueryEventHandlers: function() { - this.$element.off(); - this.$sliderElem.off(); - }, - _setText: function(element, text) { - if(typeof element.innerText !== "undefined") { - element.innerText = text; - } else if(typeof element.textContent !== "undefined") { - element.textContent = text; - } - }, - _removeClass: function(element, classString) { - var classes = classString.split(" "); - var newClasses = element.className; - - for(var i = 0; i < classes.length; i++) { - var classTag = classes[i]; - var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); - newClasses = newClasses.replace(regex, " "); - } - - element.className = newClasses.trim(); - }, - _addClass: function(element, classString) { - var classes = classString.split(" "); - var newClasses = element.className; - - for(var i = 0; i < classes.length; i++) { - var classTag = classes[i]; - var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); - var ifClassExists = regex.test(newClasses); - - if(!ifClassExists) { - newClasses += " " + classTag; - } - } - - element.className = newClasses.trim(); - }, - _offsetLeft: function(obj){ - return obj.getBoundingClientRect().left; - }, - _offsetTop: function(obj){ - var offsetTop = obj.offsetTop; - while((obj = obj.offsetParent) && !isNaN(obj.offsetTop)){ - offsetTop += obj.offsetTop; - } - return offsetTop; - }, - _offset: function (obj) { - return { - left: this._offsetLeft(obj), - top: this._offsetTop(obj) - }; - }, - _css: function(elementRef, styleName, value) { - if ($) { - $.style(elementRef, styleName, value); - } else { - var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) { - return letter.toUpperCase(); - }); - elementRef.style[style] = value; - } - }, - _toValue: function(percentage) { - return this.options.scale.toValue.apply(this, [percentage]); - }, - _toPercentage: function(value) { - return this.options.scale.toPercentage.apply(this, [value]); - }, - _setTooltipPosition: function(){ - var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max]; - if (this.options.orientation === 'vertical'){ - var tooltipPos = this.options.tooltip_position || 'right'; - var oppositeSide = (tooltipPos === 'left') ? 'right' : 'left'; - tooltips.forEach(function(tooltip){ - this._addClass(tooltip, tooltipPos); - tooltip.style[oppositeSide] = '100%'; - }.bind(this)); - } else if(this.options.tooltip_position === 'bottom') { - tooltips.forEach(function(tooltip){ - this._addClass(tooltip, 'bottom'); - tooltip.style.top = 22 + 'px'; - }.bind(this)); - } else { - tooltips.forEach(function(tooltip){ - this._addClass(tooltip, 'top'); - tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px'; - }.bind(this)); - } - } - }; - - /********************************* - - Attach to global namespace - - *********************************/ - if($) { - var namespace = $.fn.slider ? 'bootstrapSlider' : 'slider'; - $.bridget(namespace, Slider); - } - - })( $ ); - - return Slider; -})); From 27c2b3ba5e4a39d6a16acc89ed419eb5db47948e Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 26 Nov 2018 14:43:19 +0100 Subject: [PATCH 20/60] Cleanup --- src/Umbraco.Web/Actions/ActionCollection.cs | 15 ++++++++------- .../Actions/ActionCollectionBuilder.cs | 14 ++++++-------- src/Umbraco.Web/Runtime/WebRuntimeComponent.cs | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web/Actions/ActionCollection.cs b/src/Umbraco.Web/Actions/ActionCollection.cs index 64cf950c60..89ac8a59f4 100644 --- a/src/Umbraco.Web/Actions/ActionCollection.cs +++ b/src/Umbraco.Web/Actions/ActionCollection.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core; using Umbraco.Core.Composing; @@ -22,19 +21,21 @@ namespace Umbraco.Web.Actions internal IEnumerable GetByLetters(IEnumerable letters) { - var all = this.ToArray(); - return letters.Select(x => all.FirstOrDefault(y => y.Letter.ToString(CultureInfo.InvariantCulture) == x)) + var actions = this.ToArray(); // no worry: internally, it's already an array + return letters + .Where(x => x.Length == 1) + .Select(x => actions.FirstOrDefault(y => y.Letter == x[0])) .WhereNotNull() - .ToArray(); + .ToList(); } internal IReadOnlyList FromEntityPermission(EntityPermission entityPermission) { + var actions = this.ToArray(); // no worry: internally, it's already an array return entityPermission.AssignedPermissions .Where(x => x.Length == 1) - .Select(x => x.ToCharArray()[0]) - .SelectMany(c => this.Where(x => x.Letter == c)) - .Where(action => action != null) + .SelectMany(x => actions.Where(y => y.Letter == x[0])) + .WhereNotNull() .ToList(); } } diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 6002c8d2b0..079705645d 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using LightInject; using Umbraco.Core.Composing; - namespace Umbraco.Web.Actions { internal class ActionCollectionBuilder : LazyCollectionBuilderBase @@ -19,13 +17,13 @@ namespace Umbraco.Web.Actions protected override IEnumerable CreateItems(params object[] args) { var items = base.CreateItems(args).ToList(); + //validate the items, no actions should exist that do not either expose notifications or permissions - var invalid = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); - if (invalid.Count > 0) - { - throw new InvalidOperationException($"Invalid actions '{string.Join(", ", invalid.Select(x => x.Alias))}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}"); - } - return items; + var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList(); + if (invalidItems.Count == 0) return items; + + var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'")); + throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}."); } } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 1af24db636..2027cb857d 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -181,7 +181,7 @@ namespace Umbraco.Web.Runtime .Append(); composition.Container.RegisterSingleton(); - + composition.Container.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course From f8068801af229efdcf028e07b7a2eaa25d3ea61a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 26 Nov 2018 15:12:38 +0100 Subject: [PATCH 21/60] add docs --- .../components/umbrangeslider.directive.js | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js index c8a22693e3..c7b40da468 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js @@ -1,3 +1,62 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbRangeSlider +@restrict E +@scope + +@description +Added in Umbraco version 8.0 +This directive is a wrapper of the noUiSlider library. Use it to render a slider. +For extra details about options and events take a look here: https://refreshless.com/nouislider/ + +

Markup example

+
+	
+ + + + +
+
+ +

Controller example

+
+	(function () {
+		"use strict";
+
+		function Controller() {
+
+            var vm = this;
+
+            vm.value = [10];
+
+            vm.slideEnd = slideEnd;
+
+            function slideEnd(values) {
+            	// handle change
+            }
+
+        }
+
+		angular.module("umbraco").controller("My.Controller", Controller);
+
+	})();
+
+ +@param {object} ngModel (binding): Value for the slider. +@param {object} options (binding): Config object for the date picker. +@param {callback} onSetup (callback): onSetup gets triggered when the slider is initialized +@param {callback} onUpdate (callback): onUpdate fires every time the slider values are changed. +@param {callback} onSlide (callback): onSlide gets triggered when the handle is being dragged. +@param {callback} onSet (callback): onSet will trigger every time a slider stops changing. +@param {callback} onChange (callback): onChange fires when a user stops sliding, or when a slider value is changed by 'tap'. +@param {callback} onStart (callback): onStart fires when a handle is clicked (mousedown, or the equivalent touch events). +@param {callback} onEnd (callback): onEnd fires when a handle is released (mouseup etc), or when a slide is canceled due to other reasons. +**/ + + (function() { 'use strict'; From 58b1c9e9fb860368f6cbdba97c2738aaf31a373e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 26 Nov 2018 15:03:39 +0000 Subject: [PATCH 22/60] Update Serilog.Settings.AppSettings Nupkg reference from 2.1.2 to 2.2.2 in Umbraco.Core --- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 23b90aaf3c..e46fca3c99 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -89,7 +89,7 @@ 1.0.0 - 2.1.2 + 2.2.2 4.0.0 From 0983726b850270e41e3cd4004d49bbd36e21abe5 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 26 Nov 2018 15:17:15 +0000 Subject: [PATCH 23/60] Forgot to update the nuspec for the Serilog.Settings.AppSettings nuspec minor version upgrade --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index daa0018668..dd565aa1d4 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -36,7 +36,7 @@ - + From d2a474f6fff0a92e3e5dacef60979ff1a90edff8 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 09:44:08 +0100 Subject: [PATCH 24/60] ContentService should remain public for now --- src/Umbraco.Core/Services/Implement/ContentService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 0412ecb409..cd15732564 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Services.Implement /// /// Implements the content service. /// - internal class ContentService : RepositoryService, IContentService + public class ContentService : RepositoryService, IContentService { private readonly IDocumentRepository _documentRepository; private readonly IEntityRepository _entityRepository; From 4f7b9cd61aaa5625f32a7228bd79732a96d3c3c1 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 27 Nov 2018 09:50:22 +0100 Subject: [PATCH 25/60] Update umbrangeslider.directive.js Updated comment --- .../common/directives/components/umbrangeslider.directive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js index c7b40da468..0003658600 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js @@ -129,7 +129,7 @@ For extra details about options and events take a look here: https://refreshless sliderInstance.noUiSlider.set(ctrl.ngModel); } - // destroy the flatpickr instance when the dom element is removed + // destroy the slider instance when the dom element is removed angular.element(element).on('$destroy', function() { sliderInstance.noUiSlider.off(); }); @@ -204,4 +204,4 @@ For extra details about options and events take a look here: https://refreshless angular.module('umbraco.directives').component('umbRangeSlider', umbRangeSlider); -})(); \ No newline at end of file +})(); From c0f5158b030c797878c655d2a87a30a364c81444 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 27 Nov 2018 09:58:57 +0100 Subject: [PATCH 26/60] When a node is opened through a content picker don't allow editing doc type and template --- .../components/content/umbcontentnodeinfo.directive.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 78efc8f789..d2a429f813 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function ContentNodeInfoDirective($timeout, $routeParams, logResource, eventsService, userService, localizationService, dateHelper, editorService, redirectUrlsResource) { + function ContentNodeInfoDirective($timeout, logResource, eventsService, userService, localizationService, dateHelper, editorService, redirectUrlsResource) { function link(scope, element, attrs, umbVariantContentCtrl) { @@ -17,10 +17,13 @@ function onInit() { + // if there are any infinite editors open we are in infinite editing + scope.isInfiniteMode = editorService.getNumberOfEditors() > 0 ? true : false; + userService.getCurrentUser().then(function(user){ // only allow change of media type if user has access to the settings sections angular.forEach(user.sections, function(section){ - if(section.alias === "settings") { + if(section.alias === "settings" && !scope.isInfiniteMode) { scope.allowChangeDocumentType = true; scope.allowChangeTemplate = true; } From e47566ca4ea36922b50ea1071f6cc46c5f5a90a0 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 10:49:09 +0100 Subject: [PATCH 27/60] Fix build --- .../Persistence/Repositories/IDocumentBlueprintRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs index c52601d629..0148a882fd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs @@ -1,5 +1,5 @@ namespace Umbraco.Core.Persistence.Repositories { - interface IDocumentBlueprintRepository : IDocumentRepository + public interface IDocumentBlueprintRepository : IDocumentRepository { } } From 88e6797cac433251261f99845b97ff47630e4c21 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 27 Nov 2018 11:49:51 +0100 Subject: [PATCH 28/60] Refresh content when doc type is changed in infinite editing --- .../directives/components/content/edit.controller.js | 7 ------- .../components/content/umbcontentnodeinfo.directive.js | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 422c02c87c..407416f2a1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -97,13 +97,6 @@ eventsService.unsubscribe(evts[e]); } - evts.push(eventsService.on("editors.documentType.saved", function (name, args) { - // if this content item uses the updated doc type we need to reload the content item - if (args && args.documentType && args.documentType.key === $scope.content.documentType.key) { - loadContent(); - } - })); - evts.push(eventsService.on("editors.content.reload", function (name, args) { // if this content item uses the updated doc type we need to reload the content item if(args && args.node && args.node.key === $scope.content.key) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 78efc8f789..7cd10f78ff 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -87,6 +87,8 @@ var editor = { id: documentType.id, submit: function(model) { + const args = { node: scope.node }; + eventsService.emit('editors.content.reload', args); editorService.close(); }, close: function() { From 900c8355cc3f5c3fb411b74ee24750140d2a9093 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 27 Nov 2018 14:04:05 +0100 Subject: [PATCH 29/60] show prompt if node is dirty before opening the doc type editor in infinite editing --- .../content/umbcontentnodeinfo.directive.js | 41 +++++++++++++++++-- .../Umbraco/config/lang/en_us.xml | 1 + 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 7cd10f78ff..d6e25f972c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function ContentNodeInfoDirective($timeout, $routeParams, logResource, eventsService, userService, localizationService, dateHelper, editorService, redirectUrlsResource) { + function ContentNodeInfoDirective($timeout, $routeParams, logResource, eventsService, userService, localizationService, dateHelper, editorService, redirectUrlsResource, overlayService) { function link(scope, element, attrs, umbVariantContentCtrl) { @@ -32,7 +32,9 @@ "content_unpublished", "content_published", "content_publishedPendingChanges", - "content_notCreated" + "content_notCreated", + "prompt_unsavedChanges", + "prompt_doctypeChangeWarning" ]; localizationService.localizeMany(keys) @@ -42,6 +44,8 @@ labels.published = data[2]; labels.publishedPendingChanges = data[3]; labels.notCreated = data[4]; + labels.unsavedChanges = data[5]; + labels.doctypeChangeWarning = data[6]; setNodePublishStatus(scope.node); @@ -84,7 +88,36 @@ }; scope.openDocumentType = function (documentType) { - var editor = { + + const variantIsDirty = _.some(scope.node.variants, function(variant) { + return variant.isDirty; + }); + + // add confirmation dialog before opening the doc type editor + if(variantIsDirty) { + const confirm = { + title: labels.unsavedChanges, + view: "default", + content: labels.doctypeChangeWarning, + submitButtonLabelKey: "general_continue", + closeButtonLabelKey: "general_cancel", + submit: function() { + openDocTypeEditor(documentType); + overlayService.close(); + }, + close: function() { + overlayService.close(); + } + }; + overlayService.open(confirm); + } else { + openDocTypeEditor(documentType); + } + + }; + + function openDocTypeEditor(documentType) { + const editor = { id: documentType.id, submit: function(model) { const args = { node: scope.node }; @@ -96,7 +129,7 @@ } }; editorService.documentTypeEditor(editor); - }; + } scope.openTemplate = function () { var templateEditor = { 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 5b39f3d25f..fade57e934 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -340,6 +340,7 @@ Publishing will make the selected items visible on the site. Unpublishing will remove the selected items and all their descendants from the site. Unpublishing will remove this page and all its descendants from the site. + You have unsaved changes. Making changes to the Document Type will discard the changes. Done From 80f9fed3f3bf91d686b5602340b1e31631de269f Mon Sep 17 00:00:00 2001 From: Jannik Anker Date: Mon, 26 Nov 2018 13:40:13 +0100 Subject: [PATCH 30/60] Pointed "unfinished tasks" link to Github Link points to open tasks with v8 label. Not sure if "known issues" link also has a Github equivalent? --- .github/V8_GETTING_STARTED.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/V8_GETTING_STARTED.md b/.github/V8_GETTING_STARTED.md index 62b376b0e7..87ddbb166a 100644 --- a/.github/V8_GETTING_STARTED.md +++ b/.github/V8_GETTING_STARTED.md @@ -33,5 +33,5 @@ We recommend running the site with the Visual Studio since you'll be able to rem We are keeping track of [known issues and limitations here](http://issues.umbraco.org/issue/U4-11279). These line items will eventually be turned into actual tasks to be worked on. Feel free to help us keep this list updated if you find issues and even help fix some of these items. If there is a particular item you'd like to help fix please mention this on the task and we'll create a sub task for the item to continue discussion there. -There's [a list of tasks for v8 that haven't been completed](https://issues.umbraco.org/issues?q=&project=U4&tagValue=&release=8.0.0&issueType=&resolvedState=open&search=search). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done. +There's [a list of tasks for v8 that haven't been completed](hhttps://github.com/umbraco/Umbraco-CMS/labels/release%2F8.0.0). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done. From 8e423d9c75100bc978bde6d1af58d3ab8ceb4777 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 6 Nov 2018 15:56:30 +0100 Subject: [PATCH 31/60] Sort the dictionary items alphabetically --- src/Umbraco.Web/Editors/DictionaryController.cs | 8 +++++--- src/Umbraco.Web/Trees/DictionaryTreeController.cs | 7 +++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web/Editors/DictionaryController.cs b/src/Umbraco.Web/Editors/DictionaryController.cs index 7d846e68ec..cd3141c7b9 100644 --- a/src/Umbraco.Web/Editors/DictionaryController.cs +++ b/src/Umbraco.Web/Editors/DictionaryController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; @@ -194,7 +195,7 @@ namespace Umbraco.Web.Editors const int level = 0; - foreach (var dictionaryItem in Services.LocalizationService.GetRootDictionaryItems()) + foreach (var dictionaryItem in Services.LocalizationService.GetRootDictionaryItems().OrderBy(ItemSort())) { var item = Mapper.Map(dictionaryItem); item.Level = 0; @@ -220,8 +221,7 @@ namespace Umbraco.Web.Editors /// private void GetChildItemsForList(IDictionaryItem dictionaryItem, int level, List list) { - foreach (var childItem in Services.LocalizationService.GetDictionaryItemChildren( - dictionaryItem.Key)) + foreach (var childItem in Services.LocalizationService.GetDictionaryItemChildren(dictionaryItem.Key).OrderBy(ItemSort())) { var item = Mapper.Map(childItem); item.Level = level; @@ -230,5 +230,7 @@ namespace Umbraco.Web.Editors GetChildItemsForList(childItem, level + 1, list); } } + + private Func ItemSort() => item => item.ItemKey; } } diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs index d0a7fce3ad..cac2e7f435 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; +using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Actions; @@ -52,10 +53,12 @@ namespace Umbraco.Web.Trees var nodes = new TreeNodeCollection(); + Func ItemSort() => item => item.ItemKey; + if (id == Constants.System.Root.ToInvariantString()) { nodes.AddRange( - Services.LocalizationService.GetRootDictionaryItems().Select( + Services.LocalizationService.GetRootDictionaryItems().OrderBy(ItemSort()).Select( x => CreateTreeNode( x.Id.ToInvariantString(), id, @@ -71,7 +74,7 @@ namespace Umbraco.Web.Trees if (parentDictionary == null) return nodes; - nodes.AddRange(Services.LocalizationService.GetDictionaryItemChildren(parentDictionary.Key).ToList().OrderByDescending(item => item.Key).Select( + nodes.AddRange(Services.LocalizationService.GetDictionaryItemChildren(parentDictionary.Key).ToList().OrderBy(ItemSort()).Select( x => CreateTreeNode( x.Id.ToInvariantString(), id, From d62de961a05dbe0b687b98b2d1d97d8a013ac917 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 27 Nov 2018 21:09:08 +0100 Subject: [PATCH 32/60] Add a minimum height to the query builder dropdowns --- .../src/less/components/umb-querybuilder.less | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-querybuilder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-querybuilder.less index 8ead992625..151415f0db 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-querybuilder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-querybuilder.less @@ -39,4 +39,8 @@ .umb-querybuilder .query-items > * { flex: 0 1 auto; margin: 5px; -} \ No newline at end of file +} + +.umb-querybuilder .query-items .btn { + min-height: 2rem; +} From 7032f1424d9b2f763d1e0a8af160e92b28edb7ab Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 10:13:48 +0100 Subject: [PATCH 33/60] add overlay to tree when infinite editing is open --- .../src/controllers/main.controller.js | 10 +++++----- .../src/controllers/navigation.controller.js | 9 +++++++++ .../views/components/application/umb-navigation.html | 5 ++++- src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) 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 6f3f0bff52..30a7e2ac7d 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js @@ -13,7 +13,7 @@ function MainController($scope, $location, appState, treeService, notificationsS //the null is important because we do an explicit bool check on this in the view $scope.authenticated = null; $scope.touchDevice = appState.getGlobalState("touchDevice"); - $scope.editors = []; + $scope.infiniteMode = false; $scope.overlay = {}; $scope.drawer = {}; $scope.search = {}; @@ -160,12 +160,12 @@ function MainController($scope, $location, appState, treeService, notificationsS })); // event for infinite editors - evts.push(eventsService.on("appState.editors.add", function (name, args) { - $scope.editors = args.editors; + evts.push(eventsService.on("appState.editors.open", function (name, args) { + $scope.infiniteMode = args && args.editors.length > 0 ? true : false; })); - evts.push(eventsService.on("appState.editors.remove", function (name, args) { - $scope.editors = args.editors; + evts.push(eventsService.on("appState.editors.close", function (name, args) { + $scope.infiniteMode = args && args.editors.length > 0 ? true : false; })); //ensure to unregister from all events! diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index 8c521ca35e..06b82d6eab 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -241,6 +241,15 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar init(); })); + // event for infinite editors + evts.push(eventsService.on("appState.editors.open", function (name, args) { + $scope.infiniteMode = args && args.editors.length > 0 ? true : false; + })); + + evts.push(eventsService.on("appState.editors.close", function (name, args) { + $scope.infiniteMode = args && args.editors.length > 0 ? true : false; + })); + /** * Based on the current state of the application, this configures the scope variables that control the main tree and language drop down */ diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html index 9d1da590ab..c5b4f69cef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html @@ -19,7 +19,7 @@
+ on-init="onTreeInit()">
@@ -44,6 +44,9 @@ + +
+ diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml index 0d0c39aba7..4659674c59 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml @@ -67,7 +67,7 @@
-
+
From f956a035a1b98545e72201a7ba2dddef312de53a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 13:12:00 +0100 Subject: [PATCH 34/60] remove jquery validation libraries --- src/Umbraco.Web.UI.Client/gulpfile.js | 10 ---------- src/Umbraco.Web.UI.Client/package.json | 2 -- 2 files changed, 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 580acae6ca..20b0c86f4a 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -292,16 +292,6 @@ gulp.task('dependencies', function () { "src": ["./node_modules/jquery-ui-dist/jquery-ui.min.js"], "base": "./node_modules/jquery-ui-dist" }, - { - "name": "jquery-validate", - "src": ["./node_modules/jquery-validation/dist/jquery.validate.min.js"], - "base": "./node_modules/jquery-validation/dist" - }, - { - "name": "jquery-validation-unobtrusive", - "src": ["./node_modules/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"], - "base": "./node_modules/jquery-validation-unobtrusive/dist" - }, { "name": "lazyload-js", "src": ["./node_modules/lazyload-js/lazyload.min.js"], diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 63794446cd..8324d9850b 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -27,8 +27,6 @@ "jquery": "2.2.4", "jquery-migrate": "1.4.0", "jquery-ui-dist": "1.12.1", - "jquery-validation": "1.17.0", - "jquery-validation-unobtrusive": "3.2.10", "lazyload-js": "1.0.0", "moment": "2.10.6", "ng-file-upload": "12.2.13", From 4e29a3709d40778feff5180330f040a97d83a5a8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 13:16:26 +0100 Subject: [PATCH 35/60] upgrade jquery + temp add jquery migrate + temp remove other jquery libraries --- src/Umbraco.Web.UI.Client/gulpfile.js | 2 +- src/Umbraco.Web.UI.Client/package.json | 4 ++-- src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 20b0c86f4a..bf88b5b587 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -284,7 +284,7 @@ gulp.task('dependencies', function () { }, { "name": "jquery-migrate", - "src": ["./node_modules/jquery-migrate/dist/jquery-migrate.min.js"], + "src": ["./node_modules/jquery-migrate/dist/jquery-migrate.js"], "base": "./node_modules/jquery-migrate/dist" }, { diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 8324d9850b..810aab0137 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -24,8 +24,8 @@ "diff": "3.4.0", "flatpickr": "4.5.2", "font-awesome": "4.7.0", - "jquery": "2.2.4", - "jquery-migrate": "1.4.0", + "jquery": "3.3.1", + "jquery-migrate": "3.0.1", "jquery-ui-dist": "1.12.1", "lazyload-js": "1.0.0", "moment": "2.10.6", diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index eef1d25909..99583b2278 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -1,7 +1,8 @@ [ 'lib/jquery/jquery.min.js', - 'lib/jquery-ui/jquery-ui.min.js', - 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', + 'lib/jquery-migrate/jquery-migrate.js', + // 'lib/jquery-ui/jquery-ui.min.js', + // 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', 'lib/angular/angular.js', 'lib/underscore/underscore-min.js', @@ -23,7 +24,7 @@ 'lib/ng-file-upload/ng-file-upload.min.js', 'lib/angular-local-storage/angular-local-storage.min.js', - 'lib/bootstrap/js/bootstrap.2.3.2.min.js', + // 'lib/bootstrap/js/bootstrap.2.3.2.min.js', 'lib/umbraco/Extensions.js', 'lib/umbraco/NamespaceManager.js', From 85d61ee12749d96c6941bde9141ebdfe8c5f8d97 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 13:17:08 +0100 Subject: [PATCH 36/60] remove unused focus search field code --- .../src/common/services/navigation.service.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index 0ecfa375d4..23f3fb6d58 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -45,8 +45,6 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve appState.setMenuState("showMenuDialog", false); appState.setGlobalState("stickyNavigation", false); appState.setGlobalState("showTray", false); - - //$("#search-form input").focus(); break; case 'menu': appState.setGlobalState("navMode", "menu"); @@ -69,12 +67,6 @@ function navigationService($routeParams, $location, $q, $timeout, $injector, eve appState.setMenuState("showMenu", false); appState.setSectionState("showSearchResults", true); appState.setMenuState("showMenuDialog", false); - - //TODO: This would be much better off in the search field controller listening to appState changes - $timeout(function() { - $("#search-field").focus(); - }); - break; default: appState.setGlobalState("navMode", "default"); From 9c9a05f32c0e0f5e547515804c9a0aad5357d4aa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 13:22:30 +0100 Subject: [PATCH 37/60] changing from click and focus shorthands --- .../components/application/umblogin.directive.js | 9 --------- .../directives/components/forms/focuswhen.directive.js | 2 +- .../directives/components/forms/hotkey.directive.js | 6 +++--- .../components/forms/preventdefault.directive.js | 2 +- .../components/forms/umbautofocus.directive.js | 2 +- .../directives/components/grid/grid.rte.directive.js | 2 +- .../components/overlays/umboverlay.directive.js | 2 +- .../common/directives/util/umbkeyboardlist.directive.js | 4 ++-- .../mediapicker/mediapicker.controller.js | 2 +- .../src/views/components/application/umb-login.html | 6 +++--- .../test/e2e/app/admin/users/users-edit.scenario.js | 2 +- 11 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js index 6b09a8de2f..b92f8c0807 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js @@ -161,7 +161,6 @@ vm.errorMsg = ""; resetInputValidation(); vm.view = "login"; - setFieldFocus("loginForm", "username"); } function showRequestPasswordReset() { @@ -169,14 +168,12 @@ resetInputValidation(); vm.view = "request-password-reset"; vm.showEmailResetConfirmation = false; - setFieldFocus("requestPasswordResetForm", "email"); } function showSetPassword() { vm.errorMsg = ""; resetInputValidation(); vm.view = "set-password"; - setFieldFocus("setPasswordForm", "password"); } function loginSubmit(login, password) { @@ -395,12 +392,6 @@ }); } - function setFieldFocus(form, field) { - $timeout(function () { - $("form[name='" + form + "'] input[name='" + field + "']").focus(); - }); - } - function show2FALoginDialog(view, callback) { // TODO: show 2FA window } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/focuswhen.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/focuswhen.directive.js index 5d57b29175..d8dbcc1012 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/focuswhen.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/focuswhen.directive.js @@ -5,7 +5,7 @@ angular.module("umbraco.directives").directive('focusWhen', function ($timeout) attrs.$observe("focusWhen", function (newValue) { if (newValue === "true") { $timeout(function () { - elm.focus(); + elm.trigger("focus"); }); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/hotkey.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/hotkey.directive.js index 240f666632..b4040d1c77 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/hotkey.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/hotkey.directive.js @@ -43,15 +43,15 @@ angular.module("umbraco.directives") // when keycombo is enter and a link or button has focus - click the link or button instead of using the hotkey if (keyCombo === "enter" && clickableElements.indexOf(activeElementType) === 0) { - document.activeElement.click(); + document.activeElement.trigger( "click" ); } else { - element.click(); + element.trigger("click"); } } } else { - element.focus(); + element.trigger("focus"); } }, options); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/preventdefault.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/preventdefault.directive.js index df665be727..4391e39bef 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/preventdefault.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/preventdefault.directive.js @@ -25,7 +25,7 @@ angular.module("umbraco.directives") }); } - $(element).click(function (event) { + $(element).on("click", function (event) { if (event.metaKey || event.ctrlKey) { return; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautofocus.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautofocus.directive.js index bb65e94593..6fcdd99001 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautofocus.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautofocus.directive.js @@ -5,7 +5,7 @@ angular.module("umbraco.directives") var update = function() { //if it uses its default naming if(element.val() === "" || attr.focusOnFilled){ - element.focus(); + element.trigger("focus"); } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js index dc2eb75bb2..0dddada8ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js @@ -67,7 +67,7 @@ angular.module("umbraco.directives") $timeout(function () { if (scope.value === null) { - editor.focus(); + editor.trigger("focus"); } }, 400); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 07cfbb9848..851ed7c045 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -527,7 +527,7 @@ Opens an overlay to show a custom YSOD.
var submitOnEnterValue = submitOnEnter ? document.activeElement.getAttribute("overlay-submit-on-enter") : ""; if(clickableElements.indexOf(activeElementType) === 0) { - document.activeElement.click(); + document.activeElement.trigger("click"); event.preventDefault(); } else if(activeElementType === "TEXTAREA" && !submitOnEnter) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js index 1800d059c6..20572fdf16 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js @@ -87,7 +87,7 @@ angular.module('umbraco.directives') if (focusSet) { currentIndex++; } - listItems[currentIndex].focus(); + listItems[currentIndex].trigger("focus"); focusSet = true; } } @@ -95,7 +95,7 @@ angular.module('umbraco.directives') function arrowUp() { if (currentIndex > 0) { currentIndex--; - listItems[currentIndex].focus(); + listItems[currentIndex].trigger("focus"); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js index fde8d23187..c7a46c4c4a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js @@ -101,7 +101,7 @@ angular.module("umbraco") } $scope.upload = function(v) { - angular.element(".umb-file-dropzone-directive .file-select").click(); + angular.element(".umb-file-dropzone-directive .file-select").trigger("click"); }; $scope.dragLeave = function(el, event) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html index c5167ba964..7d8ce3e13e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html @@ -161,7 +161,7 @@
- +
@@ -199,7 +199,7 @@
- +
@@ -230,7 +230,7 @@
- +
diff --git a/src/Umbraco.Web.UI.Client/test/e2e/app/admin/users/users-edit.scenario.js b/src/Umbraco.Web.UI.Client/test/e2e/app/admin/users/users-edit.scenario.js index b078ad0d9b..ea17450a08 100644 --- a/src/Umbraco.Web.UI.Client/test/e2e/app/admin/users/users-edit.scenario.js +++ b/src/Umbraco.Web.UI.Client/test/e2e/app/admin/users/users-edit.scenario.js @@ -4,7 +4,7 @@ describe('admin edit user', function() { browser().navigateTo('/admin/users/new'); input('user.email').enter('admin@abc.com'); input('user.password').enter('changeme'); - element('button.login').click(); + element('button.login').trigger('click'); }); it('enables the save button when the user info is filled in correctly', function() { From f3d30342b46a1daf920d20eea601aa738f994058 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 14:32:30 +0100 Subject: [PATCH 38/60] change from bind/unbind to on/off --- .../directives/components/forms/contenteditable.directive.js | 4 ++-- .../common/directives/components/forms/fixnumber.directive.js | 2 +- .../directives/components/forms/selectonfocus.directive.js | 4 ++-- .../directives/components/forms/umbautoresize.directive.js | 4 ++-- .../directives/components/imaging/umbimagecrop.directive.js | 2 +- .../directives/components/overlays/umboverlay.directive.js | 4 ++-- .../common/directives/components/tabs/umbtabsnav.directive.js | 4 ++-- .../directives/components/upload/umbfileupload.directive.js | 2 +- .../directives/validation/showvalidationonsubmit.directive.js | 2 +- .../directives/validation/valtriggerchange.directive.js | 2 +- .../src/common/services/windowresizelistener.service.js | 2 +- .../src/views/templates/edit.controller.js | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/contenteditable.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/contenteditable.directive.js index 08eae2f378..219d42a04e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/contenteditable.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/contenteditable.directive.js @@ -14,7 +14,7 @@ angular.module("umbraco.directives") }; - element.bind("focus", function(){ + element.on("focus", function(){ var range = document.createRange(); range.selectNodeContents(element[0]); @@ -25,7 +25,7 @@ angular.module("umbraco.directives") }); - element.bind("blur keyup change", function() { + element.on("blur keyup change", function() { scope.$apply(read); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/fixnumber.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/fixnumber.directive.js index 039c189ac2..3084472332 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/fixnumber.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/fixnumber.directive.js @@ -46,7 +46,7 @@ function fixNumber($parse) { return; } - elem.bind('input', function (e) { + elem.on('input', function (e) { var validity = elem.prop('validity'); scope.$apply(function () { ctrl.$setValidity('number', !validity.badInput); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/selectonfocus.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/selectonfocus.directive.js index 1e78b88041..cb30023b29 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/selectonfocus.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/selectonfocus.directive.js @@ -1,7 +1,7 @@ angular.module("umbraco.directives") .directive('selectOnFocus', function () { return function (scope, el, attrs) { - $(el).bind("click", function () { + $(el).on("click", function () { var editmode = $(el).data("editmode"); //If editmode is true a click is handled like a normal click if (!editmode) { @@ -11,7 +11,7 @@ angular.module("umbraco.directives") $(el).data("editmode", true); } }). - bind("blur", function () { + on("blur", function () { //Reset on focus lost $(el).data("editmode", false); }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautoresize.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautoresize.directive.js index 8a456670c3..56dfb6b180 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautoresize.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbautoresize.directive.js @@ -142,8 +142,8 @@ angular.module("umbraco.directives") }); scope.$on('$destroy', function() { - element.unbind('keyup keydown keypress change', update); - element.unbind('blur', update(true)); + element.off('keyup keydown keypress change', update); + element.off('blur', update(true)); unbindModelWatcher(); // clean up IE dom element diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagecrop.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagecrop.directive.js index cdcdb7313c..ffa76a57c3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagecrop.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagecrop.directive.js @@ -266,7 +266,7 @@ angular.module("umbraco.directives") //ie hack if(window.navigator.userAgent.indexOf("MSIE ") >= 0){ var ranger = element.find("input"); - ranger.bind("change",function(){ + ranger.on("change",function(){ scope.$apply(function(){ scope.dimensions.scale.current = ranger.val(); }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 851ed7c045..d67a478aa3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -500,7 +500,7 @@ Opens an overlay to show a custom YSOD.
overlayNumber = overlayHelper.registerOverlay(); - $(document).bind("keydown.overlay-" + overlayNumber, function(event) { + $(document).on("keydown.overlay-" + overlayNumber, function(event) { if (event.which === 27) { @@ -557,7 +557,7 @@ Opens an overlay to show a custom YSOD.
overlayHelper.unregisterOverlay(); - $(document).unbind("keydown.overlay-" + overlayNumber); + $(document).off("keydown.overlay-" + overlayNumber); isRegistered = false; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js index 804bc70f1e..71fa529c84 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tabs/umbtabsnav.directive.js @@ -128,12 +128,12 @@ Use this directive to render a tabs navigation. }); } - $(window).bind('resize.tabsNav', function () { + $(window).on('resize.tabsNav', function () { calculateWidth(); }); scope.$on('$destroy', function() { - $(window).unbind('resize.tabsNav'); + $(window).off('resize.tabsNav'); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js index 6d53b20427..f93e41d0c7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js @@ -12,7 +12,7 @@ function umbFileUpload() { restrict: "A", scope: true, //create a new scope link: function (scope, el, attrs) { - el.bind('change', function (event) { + el.on('change', function (event) { var files = event.target.files; //emit event upward scope.$emit("filesSelected", { files: files }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/showvalidationonsubmit.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/showvalidationonsubmit.directive.js index 3dc48573c7..78dd00e64b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/showvalidationonsubmit.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/showvalidationonsubmit.directive.js @@ -32,7 +32,7 @@ })); //no isolate scope to listen to element destroy - element.bind('$destroy', function () { + element.on('$destroy', function () { for (var u in unsubscribe) { unsubscribe[u](); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js index 4ca7e439a3..3408a8fbaa 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtriggerchange.directive.js @@ -2,7 +2,7 @@ angular.module('umbraco.directives.validation') .directive('valTriggerChange', function($sniffer) { return { link : function(scope, elem, attrs) { - elem.bind('click', function(){ + elem.on('click', function(){ $(attrs.valTriggerChange).trigger($sniffer.hasEvent('input') ? 'input' : 'change'); }); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/windowresizelistener.service.js b/src/Umbraco.Web.UI.Client/src/common/services/windowresizelistener.service.js index 3b86510173..68691b8629 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/windowresizelistener.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/windowresizelistener.service.js @@ -31,7 +31,7 @@ function windowResizeListener($rootScope) { register: function (fn) { registered.push(fn); if (inited === false) { - $(window).bind('resize', resize); + $(window).on('resize', resize); inited = true; } }, diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index af5f4db1e6..8ac9dc78e8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -191,7 +191,7 @@ $timeout(function() { var nameField = angular.element(document.querySelector('[data-element="editor-name-field"]')); if (nameField) { - nameField.bind('blur', function(event) { + nameField.on('blur', function(event) { if (event.target.value) { vm.save(true); } From 350bfb346155ebc0c08ab018a0e8fec7a9c50200 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 14:52:49 +0100 Subject: [PATCH 39/60] remove keypress shorthand --- .../directives/components/forms/prevententersubmit.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js index 42133aa0e1..355b02216f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/prevententersubmit.directive.js @@ -16,7 +16,7 @@ angular.module("umbraco.directives") }); } - $(element).keypress(function (event) { + $(element).on("keypress", function (event) { if (event.which === 13) { event.preventDefault(); } From 6fc38b1d12f2683d286e16614b732a47e3c0487c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 14:53:39 +0100 Subject: [PATCH 40/60] fix tooltip and overlay calculations --- .../components/overlays/umboverlay.directive.js | 8 ++++---- .../common/directives/components/umbtooltip.directive.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index d67a478aa3..9f9f1aa21e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -582,12 +582,12 @@ Opens an overlay to show a custom YSOD.
var overlayIndex = overlayNumber - 1; var indentSize = overlayIndex * 20; - var overlayWidth = el.context.clientWidth; + var overlayWidth = el[0].clientWidth; el.css('width', overlayWidth - indentSize); if(scope.position === "center" && overlayIndex > 0 || scope.position === "target" && overlayIndex > 0) { - var overlayTopPosition = el.context.offsetTop; + var overlayTopPosition = el[0].offsetTop; el.css('top', overlayTopPosition + indentSize); } @@ -621,8 +621,8 @@ Opens an overlay to show a custom YSOD.
mousePositionClickY = scope.model.event.pageY; // element size - elementHeight = el.context.clientHeight; - elementWidth = el.context.clientWidth; + elementHeight = el[0].clientHeight; + elementWidth = el[0].clientWidth; // move element to this position position.left = mousePositionClickX - (elementWidth / 2); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js index d3bda41d43..34006a3cec 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js @@ -104,8 +104,8 @@ Use this directive to render a tooltip. }; // element size - elementHeight = el.context.clientHeight; - elementWidth = el.context.clientWidth; + elementHeight = el[0].clientHeight; + elementWidth = el[0].clientWidth; position.left = event.pageX - (elementWidth / 2); position.top = event.pageY; From d0d44bf54219b6142bbef843de05a409ce6c20d7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 14:54:01 +0100 Subject: [PATCH 41/60] remove unused treepicker overlay --- .../treepicker/treepicker.controller.js | 518 ------------------ 1 file changed, 518 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js deleted file mode 100644 index 827b2ad4e0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js +++ /dev/null @@ -1,518 +0,0 @@ -//used for the media picker dialog -angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", - function ($scope, $q, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService, contentResource, mediaResource, memberResource) { - - var tree = null; - var dialogOptions = $scope.model; - $scope.treeReady = false; - $scope.dialogTreeEventHandler = $({}); - $scope.section = dialogOptions.section; - $scope.treeAlias = dialogOptions.treeAlias; - $scope.multiPicker = dialogOptions.multiPicker; - $scope.hideHeader = (typeof dialogOptions.hideHeader) === "boolean" ? dialogOptions.hideHeader : true; - // if you need to load a not initialized tree set this value to false - default is true - $scope.onlyInitialized = dialogOptions.onlyInitialized; - $scope.searchInfo = { - searchFromId: dialogOptions.startNodeId, - searchFromName: null, - showSearch: false, - results: [], - selectedSearchResults: [] - } - - $scope.model.selection = []; - - //Used for toggling an empty-state message - //Some trees can have no items (dictionary & forms email templates) - $scope.hasItems = true; - $scope.emptyStateMessage = dialogOptions.emptyStateMessage; - var node = dialogOptions.currentNode; - - //This is called from ng-init - //it turns out it is called from the angular html : / Have a look at views/common / overlays / contentpicker / contentpicker.html you'll see ng-init. - //this is probably an anti pattern IMO and shouldn't be used - $scope.init = function (contentType) { - - if (contentType === "content") { - $scope.entityType = "Document"; - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectContent"); - } - } else if (contentType === "member") { - $scope.entityType = "Member"; - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMember"); - } - } else if (contentType === "media") { - $scope.entityType = "Media"; - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMedia"); - } - } - } - - var searchText = "Search..."; - localizationService.localize("general_search").then(function (value) { - searchText = value + "..."; - }); - - // Allow the entity type to be passed in but defaults to Document for backwards compatibility. - $scope.entityType = dialogOptions.entityType ? dialogOptions.entityType : "Document"; - - - //min / max values - if (dialogOptions.minNumber) { - dialogOptions.minNumber = parseInt(dialogOptions.minNumber, 10); - } - if (dialogOptions.maxNumber) { - dialogOptions.maxNumber = parseInt(dialogOptions.maxNumber, 10); - } - - if (dialogOptions.section === "member") { - $scope.entityType = "Member"; - } - else if (dialogOptions.section === "media") { - $scope.entityType = "Media"; - } - - // Search and listviews is only working for content, media and member section - var searchableSections = ["content", "media", "member"]; - - $scope.enableSearh = searchableSections.indexOf($scope.section) !== -1; - - //if a alternative startnode is used, we need to check if it is a container - if ($scope.enableSearh && dialogOptions.startNodeId && dialogOptions.startNodeId !== -1 && dialogOptions.startNodeId !== "-1") { - entityResource.getById(dialogOptions.startNodeId, $scope.entityType).then(function(node) { - if (node.metaData.IsContainer) { - openMiniListView(node); - } - initTree(); - }); - } - else { - initTree(); - } - - //Configures filtering - if (dialogOptions.filter) { - - dialogOptions.filterExclude = false; - dialogOptions.filterAdvanced = false; - - //used advanced filtering - if (angular.isFunction(dialogOptions.filter)) { - dialogOptions.filterAdvanced = true; - } - else if (angular.isObject(dialogOptions.filter)) { - dialogOptions.filterAdvanced = true; - } - else { - if (dialogOptions.filter.startsWith("!")) { - dialogOptions.filterExclude = true; - dialogOptions.filterTypes = dialogOptions.filter.substring(1); - } else { - dialogOptions.filterExclude = false; - dialogOptions.filterTypes = dialogOptions.filter; - } - - //used advanced filtering - if (dialogOptions.filter.startsWith("{")) { - dialogOptions.filterAdvanced = true; - //convert to object - dialogOptions.filter = angular.fromJson(dialogOptions.filter); - } - } - - $scope.filter = { - filterAdvanced: dialogOptions.filterAdvanced, - filterExclude: dialogOptions.filterExclude, - filter: dialogOptions.filterTypes - }; - } - - function initTree() { - //create the custom query string param for this tree - $scope.customTreeParams = dialogOptions.startNodeId ? "startNodeId=" + dialogOptions.startNodeId : ""; - $scope.customTreeParams += dialogOptions.customTreeParams ? "&" + dialogOptions.customTreeParams : ""; - $scope.treeReady = true; - } - - function nodeExpandedHandler(ev, args) { - - // open mini list view for list views - if (args.node.metaData.isContainer) { - openMiniListView(args.node); - } - - if (angular.isArray(args.children)) { - - //iterate children - _.each(args.children, function (child) { - - //now we need to look in the already selected search results and - // toggle the check boxes for those ones that are listed - var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) { - return child.id == selected.id; - }); - if (exists) { - child.selected = true; - } - }); - - //check filter - performFiltering(args.children); - } - } - - //gets the tree object when it loads - function treeLoadedHandler(ev, args) { - //args.tree contains children (args.tree.root.children) - $scope.hasItems = args.tree.root.children.length > 0; - - tree = args.tree; - - var nodeHasPath = typeof node !== "undefined" && typeof node.path !== "undefined"; - var startNodeNotDefined = typeof dialogOptions.startNodeId === "undefined" || dialogOptions.startNodeId === "" || dialogOptions.startNodeId === "-1"; - if (startNodeNotDefined && nodeHasPath) { - $scope.dialogTreeEventHandler.syncTree({ path: node.path, activate: false }); - } - - } - - //wires up selection - function nodeSelectHandler(ev, args) { - args.event.preventDefault(); - args.event.stopPropagation(); - - if (args.node.metaData.isSearchResult) { - //check if the item selected was a search result from a list view - - //unselect - select(args.node.name, args.node.id); - - //remove it from the list view children - var listView = args.node.parent(); - listView.children = _.reject(listView.children, function (child) { - return child.id == args.node.id; - }); - - //remove it from the custom tracked search result list - $scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function (i) { - return i.id == args.node.id; - }); - } - else { - eventsService.emit("dialogs.treePickerController.select", args); - - if (args.node.filtered) { - return; - } - - //This is a tree node, so we don't have an entity to pass in, it will need to be looked up - //from the server in this method. - if ($scope.model.select) { - $scope.model.select(args.node) - } else { - select(args.node.name, args.node.id); - //toggle checked state - args.node.selected = args.node.selected === true ? false : true; - } - - } - } - - /** Method used for selecting a node */ - function select(text, id, entity) { - //if we get the root, we just return a constructed entity, no need for server data - if (id < 0) { - - var rootNode = { - alias: null, - icon: "icon-folder", - id: id, - name: text - }; - - if ($scope.multiPicker) { - if (entity) { - multiSelectItem(entity); - } else { - multiSelectItem(rootNode); - } - } - else { - $scope.model.selection.push(rootNode); - $scope.model.submit($scope.model); - } - } - else { - - if ($scope.multiPicker) { - - if (entity) { - multiSelectItem(entity); - } else { - //otherwise we have to get it from the server - entityResource.getById(id, $scope.entityType).then(function (ent) { - multiSelectItem(ent); - }); - } - - } - - else { - - $scope.hideSearch(); - - //if an entity has been passed in, use it - if (entity) { - $scope.model.selection.push(entity); - $scope.model.submit($scope.model); - } else { - //otherwise we have to get it from the server - entityResource.getById(id, $scope.entityType).then(function (ent) { - $scope.model.selection.push(ent); - $scope.model.submit($scope.model); - }); - } - } - } - } - - function multiSelectItem(item) { - - var found = false; - var foundIndex = 0; - - if ($scope.model.selection.length > 0) { - for (var i = 0; $scope.model.selection.length > i; i++) { - var selectedItem = $scope.model.selection[i]; - if (selectedItem.id === item.id) { - found = true; - foundIndex = i; - } - } - } - - if (found) { - $scope.model.selection.splice(foundIndex, 1); - } else { - $scope.model.selection.push(item); - } - - } - - function performFiltering(nodes) { - - if (!dialogOptions.filter) { - return; - } - - //remove any list view search nodes from being filtered since these are special nodes that always must - // be allowed to be clicked on - nodes = _.filter(nodes, function (n) { - return !angular.isObject(n.metaData.listViewNode); - }); - - if (dialogOptions.filterAdvanced) { - - //filter either based on a method or an object - var filtered = angular.isFunction(dialogOptions.filter) - ? _.filter(nodes, dialogOptions.filter) - : _.where(nodes, dialogOptions.filter); - - angular.forEach(filtered, function (value, key) { - value.filtered = true; - if (dialogOptions.filterCssClass) { - if (!value.cssClasses) { - value.cssClasses = []; - } - value.cssClasses.push(dialogOptions.filterCssClass); - } - }); - } else { - var a = dialogOptions.filterTypes.toLowerCase().replace(/\s/g, '').split(','); - angular.forEach(nodes, function (value, key) { - - var found = a.indexOf(value.metaData.contentType.toLowerCase()) >= 0; - - if (!dialogOptions.filterExclude && !found || dialogOptions.filterExclude && found) { - value.filtered = true; - - if (dialogOptions.filterCssClass) { - if (!value.cssClasses) { - value.cssClasses = []; - } - value.cssClasses.push(dialogOptions.filterCssClass); - } - } - }); - } - } - - $scope.multiSubmit = function (result) { - entityResource.getByIds(result, $scope.entityType).then(function (ents) { - $scope.submit(ents); - }); - }; - - /** method to select a search result */ - $scope.selectResult = function (evt, result) { - - if (result.filtered) { - return; - } - - result.selected = result.selected === true ? false : true; - - //since result = an entity, we'll pass it in so we don't have to go back to the server - select(result.name, result.id, result); - - //add/remove to our custom tracked list of selected search results - if (result.selected) { - $scope.searchInfo.selectedSearchResults.push(result); - } - else { - $scope.searchInfo.selectedSearchResults = _.reject($scope.searchInfo.selectedSearchResults, function (i) { - return i.id == result.id; - }); - } - - //ensure the tree node in the tree is checked/unchecked if it already exists there - if (tree) { - var found = treeService.getDescendantNode(tree.root, result.id); - if (found) { - found.selected = result.selected; - } - } - - }; - - $scope.hideSearch = function () { - - //Traverse the entire displayed tree and update each node to sync with the selected search results - if (tree) { - - //we need to ensure that any currently displayed nodes that get selected - // from the search get updated to have a check box! - function checkChildren(children) { - _.each(children, function (child) { - //check if the id is in the selection, if so ensure it's flagged as selected - var exists = _.find($scope.searchInfo.selectedSearchResults, function (selected) { - return child.id == selected.id; - }); - //if the curr node exists in selected search results, ensure it's checked - if (exists) { - child.selected = true; - } - //if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result - else if (child.metaData.isSearchResult) { - //if this tree node is under a list view it means that the node was added - // to the tree dynamically under the list view that was searched, so we actually want to remove - // it all together from the tree - var listView = child.parent(); - listView.children = _.reject(listView.children, function (c) { - return c.id == child.id; - }); - } - - //check if the current node is a list view and if so, check if there's any new results - // that need to be added as child nodes to it based on search results selected - if (child.metaData.isContainer) { - - child.cssClasses = _.reject(child.cssClasses, function (c) { - return c === 'tree-node-slide-up-hide-active'; - }); - - var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function (i) { - return i.parentId == child.id; - }); - _.each(listViewResults, function (item) { - var childExists = _.find(child.children, function (c) { - return c.id == item.id; - }); - if (!childExists) { - var parent = child; - child.children.unshift({ - id: item.id, - name: item.name, - cssClass: "icon umb-tree-icon sprTree " + item.icon, - level: child.level + 1, - metaData: { - isSearchResult: true - }, - hasChildren: false, - parent: function () { - return parent; - } - }); - } - }); - } - - //recurse - if (child.children && child.children.length > 0) { - checkChildren(child.children); - } - }); - } - checkChildren(tree.root.children); - } - - - $scope.searchInfo.showSearch = false; - $scope.searchInfo.searchFromId = dialogOptions.startNodeId; - $scope.searchInfo.searchFromName = null; - $scope.searchInfo.results = []; - } - - $scope.onSearchResults = function (results) { - - //filter all items - this will mark an item as filtered - performFiltering(results); - - //now actually remove all filtered items so they are not even displayed - results = _.filter(results, function (item) { - return !item.filtered; - }); - - $scope.searchInfo.results = results; - - //sync with the curr selected results - _.each($scope.searchInfo.results, function (result) { - var exists = _.find($scope.model.selection, function (selectedId) { - return result.id == selectedId; - }); - if (exists) { - result.selected = true; - } - }); - - $scope.searchInfo.showSearch = true; - }; - - $scope.dialogTreeEventHandler.bind("treeLoaded", treeLoadedHandler); - $scope.dialogTreeEventHandler.bind("treeNodeExpanded", nodeExpandedHandler); - $scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler); - - $scope.$on('$destroy', function () { - $scope.dialogTreeEventHandler.unbind("treeLoaded", treeLoadedHandler); - $scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler); - $scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler); - }); - - $scope.selectListViewNode = function (node) { - select(node.name, node.id); - //toggle checked state - node.selected = node.selected === true ? false : true; - }; - - $scope.closeMiniListView = function () { - $scope.miniListView = undefined; - }; - - function openMiniListView(node) { - $scope.miniListView = node; - } - - }); From df193987c4d98a2330be846bdee29660eb3b7401 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 15:18:14 +0100 Subject: [PATCH 42/60] add back jquery-ui and remove jquery-migrate --- src/Umbraco.Web.UI.Client/gulpfile.js | 5 ----- src/Umbraco.Web.UI.Client/package.json | 1 - src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 7 +++---- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index bf88b5b587..95a9325f9a 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -282,11 +282,6 @@ gulp.task('dependencies', function () { ], "base": "./node_modules/jquery/dist" }, - { - "name": "jquery-migrate", - "src": ["./node_modules/jquery-migrate/dist/jquery-migrate.js"], - "base": "./node_modules/jquery-migrate/dist" - }, { "name": "jquery-ui", "src": ["./node_modules/jquery-ui-dist/jquery-ui.min.js"], diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 810aab0137..9e4a7d37f2 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -25,7 +25,6 @@ "flatpickr": "4.5.2", "font-awesome": "4.7.0", "jquery": "3.3.1", - "jquery-migrate": "3.0.1", "jquery-ui-dist": "1.12.1", "lazyload-js": "1.0.0", "moment": "2.10.6", diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index 99583b2278..eef1d25909 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -1,8 +1,7 @@ [ 'lib/jquery/jquery.min.js', - 'lib/jquery-migrate/jquery-migrate.js', - // 'lib/jquery-ui/jquery-ui.min.js', - // 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', + 'lib/jquery-ui/jquery-ui.min.js', + 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', 'lib/angular/angular.js', 'lib/underscore/underscore-min.js', @@ -24,7 +23,7 @@ 'lib/ng-file-upload/ng-file-upload.min.js', 'lib/angular-local-storage/angular-local-storage.min.js', - // 'lib/bootstrap/js/bootstrap.2.3.2.min.js', + 'lib/bootstrap/js/bootstrap.2.3.2.min.js', 'lib/umbraco/Extensions.js', 'lib/umbraco/NamespaceManager.js', From e4a4a17739dbd254ba9f53adce57b0ab8e5ec9f4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 15:34:51 +0100 Subject: [PATCH 43/60] get jquery touch punch from npm --- src/Umbraco.Web.UI.Client/gulpfile.js | 5 + .../jquery.ui.touch-punch.js | 180 ------------------ src/Umbraco.Web.UI.Client/package.json | 1 + src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 2 +- 4 files changed, 7 insertions(+), 181 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 95a9325f9a..f9d21c701a 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -287,6 +287,11 @@ gulp.task('dependencies', function () { "src": ["./node_modules/jquery-ui-dist/jquery-ui.min.js"], "base": "./node_modules/jquery-ui-dist" }, + { + "name": "jquery-ui-touch-punch", + "src": ["./node_modules/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"], + "base": "./node_modules/jquery-ui-touch-punch" + }, { "name": "lazyload-js", "src": ["./node_modules/lazyload-js/lazyload.min.js"], diff --git a/src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js b/src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js deleted file mode 100644 index b395b9a372..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js +++ /dev/null @@ -1,180 +0,0 @@ -/*! - * jQuery UI Touch Punch 0.2.3 - * - * Copyright 2011–2014, Dave Furfero - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Depends: - * jquery.ui.widget.js - * jquery.ui.mouse.js - */ -(function ($) { - - // Detect touch support - $.support.touch = 'ontouchend' in document; - - // Ignore browsers without touch support - if (!$.support.touch) { - return; - } - - var mouseProto = $.ui.mouse.prototype, - _mouseInit = mouseProto._mouseInit, - _mouseDestroy = mouseProto._mouseDestroy, - touchHandled; - - /** - * Simulate a mouse event based on a corresponding touch event - * @param {Object} event A touch event - * @param {String} simulatedType The corresponding mouse event - */ - function simulateMouseEvent (event, simulatedType) { - - // Ignore multi-touch events - if (event.originalEvent.touches.length > 1) { - return; - } - - event.preventDefault(); - - var touch = event.originalEvent.changedTouches[0], - simulatedEvent = document.createEvent('MouseEvents'); - - // Initialize the simulated mouse event using the touch event's coordinates - simulatedEvent.initMouseEvent( - simulatedType, // type - true, // bubbles - true, // cancelable - window, // view - 1, // detail - touch.screenX, // screenX - touch.screenY, // screenY - touch.clientX, // clientX - touch.clientY, // clientY - false, // ctrlKey - false, // altKey - false, // shiftKey - false, // metaKey - 0, // button - null // relatedTarget - ); - - // Dispatch the simulated event to the target element - event.target.dispatchEvent(simulatedEvent); - } - - /** - * Handle the jQuery UI widget's touchstart events - * @param {Object} event The widget element's touchstart event - */ - mouseProto._touchStart = function (event) { - - var self = this; - - // Ignore the event if another widget is already being handled - if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { - return; - } - - // Set the flag to prevent other widgets from inheriting the touch event - touchHandled = true; - - // Track movement to determine if interaction was a click - self._touchMoved = false; - - // Simulate the mouseover event - simulateMouseEvent(event, 'mouseover'); - - // Simulate the mousemove event - simulateMouseEvent(event, 'mousemove'); - - // Simulate the mousedown event - simulateMouseEvent(event, 'mousedown'); - }; - - /** - * Handle the jQuery UI widget's touchmove events - * @param {Object} event The document's touchmove event - */ - mouseProto._touchMove = function (event) { - - // Ignore event if not handled - if (!touchHandled) { - return; - } - - // Interaction was not a click - this._touchMoved = true; - - // Simulate the mousemove event - simulateMouseEvent(event, 'mousemove'); - }; - - /** - * Handle the jQuery UI widget's touchend events - * @param {Object} event The document's touchend event - */ - mouseProto._touchEnd = function (event) { - - // Ignore event if not handled - if (!touchHandled) { - return; - } - - // Simulate the mouseup event - simulateMouseEvent(event, 'mouseup'); - - // Simulate the mouseout event - simulateMouseEvent(event, 'mouseout'); - - // If the touch interaction did not move, it should trigger a click - if (!this._touchMoved) { - - // Simulate the click event - simulateMouseEvent(event, 'click'); - } - - // Unset the flag to allow other widgets to inherit the touch event - touchHandled = false; - }; - - /** - * A duck punch of the $.ui.mouse _mouseInit method to support touch events. - * This method extends the widget with bound touch event handlers that - * translate touch events to mouse events and pass them to the widget's - * original mouse event handling methods. - */ - mouseProto._mouseInit = function () { - - var self = this; - - // Delegate the touch handlers to the widget's element - self.element.bind({ - touchstart: $.proxy(self, '_touchStart'), - touchmove: $.proxy(self, '_touchMove'), - touchend: $.proxy(self, '_touchEnd') - }); - - // Call the original $.ui.mouse init method - _mouseInit.call(self); - }; - - /** - * Remove the touch event handlers - */ - mouseProto._mouseDestroy = function () { - - var self = this; - - // Delegate the touch handlers to the widget's element - self.element.unbind({ - touchstart: $.proxy(self, '_touchStart'), - touchmove: $.proxy(self, '_touchMove'), - touchend: $.proxy(self, '_touchEnd') - }); - - // Call the original $.ui.mouse destroy method - _mouseDestroy.call(self); - }; - -})(jQuery); diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 9e4a7d37f2..51cca5d658 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -26,6 +26,7 @@ "font-awesome": "4.7.0", "jquery": "3.3.1", "jquery-ui-dist": "1.12.1", + "jquery-ui-touch-punch": "^0.2.3", "lazyload-js": "1.0.0", "moment": "2.10.6", "ng-file-upload": "12.2.13", diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index eef1d25909..94190ccb73 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -1,7 +1,7 @@ [ 'lib/jquery/jquery.min.js', 'lib/jquery-ui/jquery-ui.min.js', - 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', + 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js', 'lib/angular/angular.js', 'lib/underscore/underscore-min.js', From e512ba0b8b5080acf3918781c9f10ebb7f299366 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 20:40:40 +0100 Subject: [PATCH 44/60] remove css for jquery-ui --- .../lib/jquery-ui/jquery-ui-1.10.4.custom.min.css | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css diff --git a/src/Umbraco.Web.UI.Client/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css b/src/Umbraco.Web.UI.Client/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css deleted file mode 100644 index 3f336f6698..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.10.4 - 2014-02-23 -* http://jqueryui.com -* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px -* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px} \ No newline at end of file From 44478201cfc4b2d3417378d11ff09555ffc7a7c7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 28 Nov 2018 20:47:02 +0100 Subject: [PATCH 45/60] update package-lock --- src/Umbraco.Web.UI.Client/package-lock.json | 2760 ++++++++++++++++++- 1 file changed, 2729 insertions(+), 31 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index a53244f131..c0a4cb370c 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -5497,12 +5497,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5517,17 +5519,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5644,7 +5649,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5656,6 +5662,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5670,6 +5677,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5677,12 +5685,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5701,6 +5711,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5781,7 +5792,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5793,6 +5805,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5914,6 +5927,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8522,36 +8536,19 @@ } }, "jquery": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", - "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" - }, - "jquery-migrate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-1.4.0.tgz", - "integrity": "sha1-4AKOSDHMFH2PIvOCBRbr+5dReaU=" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" }, "jquery-ui-dist": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz", "integrity": "sha1-XAgV08xvkP9fqvWyaKbiO0ypBPo=" }, - "jquery-validation": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.17.0.tgz", - "integrity": "sha512-XddiAwhGdWhcIJ+W3ri3KG8uTPMua4TPYuUIC8/E7lOyqdScG5xHuy9YishlKc0c/lIQai77EX7hxMdTSYCEjA==", - "requires": { - "jquery": "^1.7 || ^2.0 || ^3.1" - } - }, - "jquery-validation-unobtrusive": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-3.2.10.tgz", - "integrity": "sha512-z9ZBP/HslaGNKzFSpfLNJoFm2iqPJfE6CKM0H5e9LmKnYTFxErvCFQZomOLiTmLmZi8Wi/otW38cEXExVDha0w==", - "requires": { - "jquery": ">=1.8", - "jquery-validation": ">=1.16" - } + "jquery-ui-touch-punch": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/jquery-ui-touch-punch/-/jquery-ui-touch-punch-0.2.3.tgz", + "integrity": "sha1-7tgiQnM7okP0az6HwYQbMIGR2mg=" }, "js-base64": { "version": "2.4.9", @@ -10291,6 +10288,2707 @@ "sort-keys": "^1.0.0" } }, + "nouislider": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-12.1.0.tgz", + "integrity": "sha512-SAOabF6hBm8201c6LDbkVOVhgwY49+/ms72ZLUF2qkN5RCf7FfUvEh/hGZ7XcwZHU+I/grlicPmcSk1/rrMnOw==" + }, + "npm": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", + "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", + "requires": { + "JSONStream": "^1.3.4", + "abbrev": "~1.1.1", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "aproba": "~1.2.0", + "archy": "~1.0.0", + "bin-links": "^1.1.2", + "bluebird": "~3.5.1", + "byte-size": "^4.0.3", + "cacache": "^11.2.0", + "call-limit": "~1.1.0", + "chownr": "~1.0.1", + "ci-info": "^1.4.0", + "cli-columns": "^3.1.2", + "cli-table3": "^0.5.0", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.11", + "debuglog": "*", + "detect-indent": "~5.0.0", + "detect-newline": "^2.1.0", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "figgy-pudding": "^3.4.1", + "find-npm-prefix": "^1.0.2", + "fs-vacuum": "~1.2.10", + "fs-write-stream-atomic": "~1.0.10", + "gentle-fs": "^2.0.1", + "glob": "~7.1.2", + "graceful-fs": "~4.1.11", + "has-unicode": "~2.0.1", + "hosted-git-info": "^2.7.1", + "iferr": "^1.0.2", + "imurmurhash": "*", + "inflight": "~1.0.6", + "inherits": "~2.0.3", + "ini": "^1.3.5", + "init-package-json": "^1.10.3", + "is-cidr": "^2.0.6", + "json-parse-better-errors": "^1.0.2", + "lazy-property": "~1.0.0", + "libcipm": "^2.0.2", + "libnpmhook": "^4.0.1", + "libnpx": "^10.2.0", + "lock-verify": "^2.0.2", + "lockfile": "^1.0.4", + "lodash._baseindexof": "*", + "lodash._baseuniq": "~4.6.0", + "lodash._bindcallback": "*", + "lodash._cacheindexof": "*", + "lodash._createcache": "*", + "lodash._getnative": "*", + "lodash.clonedeep": "~4.5.0", + "lodash.restparam": "*", + "lodash.union": "~4.6.0", + "lodash.uniq": "~4.5.0", + "lodash.without": "~4.4.0", + "lru-cache": "^4.1.3", + "meant": "~1.0.1", + "mississippi": "^3.0.0", + "mkdirp": "~0.5.1", + "move-concurrently": "^1.0.1", + "node-gyp": "^3.8.0", + "nopt": "~4.0.1", + "normalize-package-data": "~2.4.0", + "npm-audit-report": "^1.3.1", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~3.0.0", + "npm-lifecycle": "^2.1.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.11", + "npm-pick-manifest": "^2.1.0", + "npm-profile": "^3.0.2", + "npm-registry-client": "^8.6.0", + "npm-registry-fetch": "^1.1.0", + "npm-user-validate": "~1.0.0", + "npmlog": "~4.1.2", + "once": "~1.4.0", + "opener": "^1.5.0", + "osenv": "^0.1.5", + "pacote": "^8.1.6", + "path-is-inside": "~1.0.2", + "promise-inflight": "~1.0.1", + "qrcode-terminal": "^0.12.0", + "query-string": "^6.1.0", + "qw": "~1.0.1", + "read": "~1.0.7", + "read-cmd-shim": "~1.0.1", + "read-installed": "~4.0.3", + "read-package-json": "^2.0.13", + "read-package-tree": "^5.2.1", + "readable-stream": "^2.3.6", + "readdir-scoped-modules": "*", + "request": "^2.88.0", + "retry": "^0.12.0", + "rimraf": "~2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.1", + "sorted-union-stream": "~2.1.3", + "ssri": "^6.0.0", + "stringify-package": "^1.0.0", + "tar": "^4.4.6", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "unique-filename": "~1.1.0", + "unpipe": "~1.0.0", + "update-notifier": "^2.5.0", + "uuid": "^3.3.2", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "~3.0.0", + "which": "^1.3.1", + "worker-farm": "^1.6.0", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.4", + "bundled": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ajv": { + "version": "5.5.2", + "bundled": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-links": { + "version": "1.1.2", + "bundled": true, + "requires": { + "bluebird": "^3.5.0", + "cmd-shim": "^2.0.2", + "gentle-fs": "^2.0.0", + "graceful-fs": "^4.1.11", + "write-file-atomic": "^2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, + "byte-size": { + "version": "4.0.3", + "bundled": true + }, + "cacache": { + "version": "11.2.0", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "figgy-pudding": "^3.1.0", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.0", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "ci-info": { + "version": "1.4.0", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "^2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.1.2", + "bundled": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.4.1", + "bundled": true + }, + "find-npm-prefix": { + "version": "1.0.2", + "bundled": true + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.2", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, + "gentle-fs": { + "version": "2.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.2", + "fs-vacuum": "^1.2.10", + "graceful-fs": "^4.1.11", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "path-is-inside": "^1.0.2", + "read-cmd-shim": "^1.0.1", + "slide": "^1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "^1.3.4" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.0", + "bundled": true, + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "iferr": { + "version": "1.0.2", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "init-package-json": { + "version": "1.10.3", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "^2.0.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "libcipm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "bin-links": "^1.1.2", + "bluebird": "^3.5.1", + "find-npm-prefix": "^1.0.2", + "graceful-fs": "^4.1.11", + "lock-verify": "^2.0.2", + "mkdirp": "^0.5.1", + "npm-lifecycle": "^2.0.3", + "npm-logical-tree": "^1.2.1", + "npm-package-arg": "^6.1.0", + "pacote": "^8.1.6", + "protoduck": "^5.0.0", + "read-package-json": "^2.0.13", + "rimraf": "^2.6.2", + "worker-farm": "^1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "^3.1.0", + "npm-registry-fetch": "^3.0.0" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.1.0", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^4.0.0", + "npm-package-arg": "^6.0.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "bundled": true, + "requires": { + "dotenv": "^5.0.1", + "npm-package-arg": "^6.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.0", + "update-notifier": "^2.3.0", + "which": "^1.3.0", + "y18n": "^4.0.0", + "yargs": "^11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "^5.1.2 || 6", + "semver": "^5.4.1" + } + }, + "lockfile": { + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "^3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "^3.0.0" + } + }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^11.0.1", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "bundled": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.35.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.19", + "bundled": true, + "requires": { + "mime-db": "~1.35.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mississippi": { + "version": "3.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "3.8.0", + "bundled": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "bundled": true, + "requires": { + "cli-table3": "^0.5.0", + "console-control-strings": "^1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true, + "requires": { + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-lifecycle": { + "version": "2.1.0", + "bundled": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.11", + "node-gyp": "^3.8.0", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, + "npm-package-arg": { + "version": "6.1.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-profile": { + "version": "3.0.2", + "bundled": true, + "requires": { + "aproba": "^1.1.2 || 2", + "make-fetch-happen": "^2.5.0 || 3 || 4" + } + }, + "npm-registry-client": { + "version": "8.6.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^2.0.1", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^3.0.0", + "npm-package-arg": "^6.0.0", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^10.0.4", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.0", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^3.0.1", + "ssri": "^5.2.4" + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "bundled": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.0", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pacote": { + "version": "8.1.6", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "cacache": "^11.0.2", + "get-stream": "^3.0.0", + "glob": "^7.1.2", + "lru-cache": "^4.1.3", + "make-fetch-happen": "^4.0.1", + "minimatch": "^3.0.4", + "minipass": "^2.3.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.10", + "npm-pick-manifest": "^2.1.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "ssri": "^6.0.0", + "tar": "^4.4.3", + "unique-filename": "^1.1.0", + "which": "^1.3.0" + } + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "^4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.29", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "query-string": { + "version": "6.1.0", + "bundled": true, + "requires": { + "decode-uri-component": "^0.2.0", + "strict-uri-encode": "^2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "read": { + "version": "1.0.7", + "bundled": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.0.13", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "slash": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "once": "^1.3.0", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "^1.0.1" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "^5.0.3" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "requires": { + "from2": "^1.3.0", + "stream-iterate": "^1.1.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.10" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-package": { + "version": "1.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "4.4.6", + "bundled": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "^0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "^1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "bundled": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "bundled": true + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", From 1daddf484c58370d5d21c59160924ae17863cb93 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 11:00:09 +0100 Subject: [PATCH 46/60] update npm for packages not running latest --- src/Umbraco.Web.UI.Client/package-lock.json | 99 +++++++++------------ src/Umbraco.Web.UI.Client/package.json | 18 ++-- 2 files changed, 52 insertions(+), 65 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index c0a4cb370c..ab1610cb4d 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -859,9 +859,9 @@ } }, "ace-builds": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.3.3.tgz", - "integrity": "sha512-PbSdoHw42kt5vaXkEVSfUYCd3K1BCfAvyXW9TvR/2ATkk65oImjS1v0evHmzHhOYPSTUO8BprvmpfYT9Vp2akA==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.4.2.tgz", + "integrity": "sha512-M1JtZctO2Zg+1qeGUFZXtYKsyaRptqQtqpVzlj80I0NzGW9MF3um0DBuizIvQlrPYUlTdm+wcOPZpZoerkxQdA==" }, "acorn": { "version": "5.7.3", @@ -1025,9 +1025,14 @@ "integrity": "sha512-XNAZNG0RA1mtdwBJheViCF1H/7wOygp4MLIfs5y1K+rne6AeaYKZcV6EJs9fvgfLKLO6ecm1+3J8hoCkdhhxQw==" }, "angular-ui-sortable": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.15.0.tgz", - "integrity": "sha1-8kLlH4Uic34+9ndUC3J4dyxQzCA=" + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.19.0.tgz", + "integrity": "sha512-u/uc981Nzg4XN1bMU9qKleMTSt7F1XjMWnyGw6gxPLIeQeLZm8jWNy7tj8y2r2HmvzXFbQVq2z6rObznFKAekQ==", + "requires": { + "angular": ">=1.2.x", + "jquery": ">=3.1.x", + "jquery-ui-dist": ">=1.12.x" + } }, "animejs": { "version": "2.2.0", @@ -1772,19 +1777,12 @@ "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=" }, "bootstrap-social": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/bootstrap-social/-/bootstrap-social-4.8.0.tgz", - "integrity": "sha1-ZtRj3JZtbbQH37mTNR1YxTSqLHo=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bootstrap-social/-/bootstrap-social-5.1.1.tgz", + "integrity": "sha1-dTDGeK31bPj60/qCwp1NPl0CdQE=", "requires": { "bootstrap": "~3", - "font-awesome": "~4.3" - }, - "dependencies": { - "font-awesome": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.3.0.tgz", - "integrity": "sha1-RO63kM35hmQnhvM/znhHZPGEHEA=" - } + "font-awesome": "~4.7" } }, "bower": { @@ -2278,9 +2276,9 @@ "dev": true }, "clipboard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.0.tgz", - "integrity": "sha512-gXzHBlzEVqCk2b8Wpkil89S0WSMAX7eZho2zANX+EEEa9LMutGe9ICU+wHRzsH7cCHaCbUzj900P+AXOM0FE3A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", + "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", "requires": { "good-listener": "^1.2.2", "select": "^1.1.2", @@ -3666,9 +3664,9 @@ "dev": true }, "diff": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "doctrine": { "version": "2.1.0", @@ -5497,14 +5495,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5519,20 +5515,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5649,8 +5642,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5662,7 +5654,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5677,7 +5668,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5685,14 +5675,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5711,7 +5699,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5792,8 +5779,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5805,7 +5791,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5927,7 +5912,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -9983,9 +9967,9 @@ } }, "moment": { - "version": "2.10.6", - "resolved": "http://registry.npmjs.org/moment/-/moment-2.10.6.tgz", - "integrity": "sha1-bLIZZ8ecunsMpeZmRPFzZis++nc=" + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" }, "morgan": { "version": "1.6.1", @@ -15130,9 +15114,9 @@ "dev": true }, "signalr": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.3.0.tgz", - "integrity": "sha512-NrvIGftLz3QVujdjCvaNso56ltTr1FowSR0DCIaSOJ3J4t5pTebTfnh2VT0HHIM3PJ/v15lukIL4y+8MMknqzg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/signalr/-/signalr-2.4.0.tgz", + "integrity": "sha512-GPJHb3pcNk3IUui5/WG8lMuarEn+Vpc8wEvJ60w0KQ43W9FHnJcuNcF8dkZePr81eBslzicsRdyEunKNF7KjZQ==", "requires": { "jquery": ">=1.6.4" } @@ -16217,9 +16201,9 @@ } }, "tinymce": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.8.3.tgz", - "integrity": "sha512-kNEsKTqUYZRG+GTZ7tcVAktUlDeApz6d3IqnNaZXNX0CP0BsK8NPC02FCJ0EVYxdNnq6fvvknWkItmbreXD9aA==" + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.9.0.tgz", + "integrity": "sha512-hrPeCLXY/sVCo3i64CTW8P5xbDiEI8Uii/vWpcmQWAMhex6GWWd2U+L8WIMj5tKKGdfcIQAJfpfQthc/92bcKw==" }, "tmp": { "version": "0.0.33", @@ -16399,9 +16383,12 @@ } }, "typeahead.js": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.10.5.tgz", - "integrity": "sha1-HZlxsPRNOF/q2/IsnzadtWKRLeE=" + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/typeahead.js/-/typeahead.js-0.11.1.tgz", + "integrity": "sha1-TmTmcbIjEKhgb0rsgFkkuoSwFbg=", + "requires": { + "jquery": ">=1.7" + } }, "typedarray": { "version": "0.0.6", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 51cca5d658..66efdd97a8 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -5,7 +5,7 @@ "build": "gulp" }, "dependencies": { - "ace-builds": "1.3.3", + "ace-builds": "1.4.2", "angular": "1.7.5", "angular-animate": "1.7.5", "angular-cookies": "1.7.5", @@ -17,24 +17,24 @@ "angular-route": "1.7.5", "angular-sanitize": "1.7.5", "angular-touch": "1.7.5", - "angular-ui-sortable": "0.15.0", + "angular-ui-sortable": "0.19.0", "animejs": "2.2.0", - "bootstrap-social": "4.8.0", - "clipboard": "2.0.0", - "diff": "3.4.0", + "bootstrap-social": "5.1.1", + "clipboard": "2.0.4", + "diff": "3.5.0", "flatpickr": "4.5.2", "font-awesome": "4.7.0", "jquery": "3.3.1", "jquery-ui-dist": "1.12.1", "jquery-ui-touch-punch": "^0.2.3", "lazyload-js": "1.0.0", - "moment": "2.10.6", + "moment": "2.22.2", "ng-file-upload": "12.2.13", "nouislider": "12.1.0", "npm": "^6.4.1", - "signalr": "2.3.0", - "tinymce": "4.8.3", - "typeahead.js": "0.10.5", + "signalr": "2.4.0", + "tinymce": "4.9.0", + "typeahead.js": "0.11.1", "underscore": "1.9.1" }, "devDependencies": { From aa9950ff29b7f7159843251bd63d7062505bc61b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 11:01:21 +0100 Subject: [PATCH 47/60] fix assets service --- src/Umbraco.Web.UI.Client/src/common/services/assets.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js index e7f40f4814..27e055a7d3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js @@ -96,7 +96,7 @@ angular.module('umbraco.services') function loadLocales(locales, supportedLocales) { var localeUrls = getMomentLocales(locales, supportedLocales); if (localeUrls.length >= 1) { - return assetsService.load(localeUrls, $rootScope); + return service.load(localeUrls, $rootScope); } else { $q.when(true); From 89cac781aed6b78076d77d372445877e1d3588d5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 11:01:50 +0100 Subject: [PATCH 48/60] fix checkmark when copying password --- .../users/views/users/users.controller.js | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index d78095a90f..2b531b7ef2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -531,26 +531,24 @@ // copy to clip board success function copySuccess() { - - if (vm.page.copyPasswordButtonState != "success") { - - vm.page.copyPasswordButtonState = "success"; - + if (vm.page.copyPasswordButtonState !== "success") { + $timeout(function(){ + vm.page.copyPasswordButtonState = "success"; + }); $timeout(function () { - resetClipboardButtonState() + resetClipboardButtonState(); }, 1000); } - } // copy to clip board error function copyError() { - if (vm.page.copyPasswordButtonState != "error") { - - vm.page.copyPasswordButtonState = "error"; - + if (vm.page.copyPasswordButtonState !== "error") { + $timeout(function() { + vm.page.copyPasswordButtonState = "error"; + }); $timeout(function () { - resetClipboardButtonState() + resetClipboardButtonState(); }, 1000); } } From 5a33990a746ebcf9844814f192933c98ebeae9d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 12:29:52 +0100 Subject: [PATCH 49/60] fix js error in diff + break words --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/utilities/typography/_word-break.less | 7 +++++++ .../common/infiniteeditors/rollback/rollback.controller.js | 7 +++++-- .../views/common/infiniteeditors/rollback/rollback.html | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/utilities/typography/_word-break.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 5d00d6f749..3f39c5c13f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -177,6 +177,7 @@ @import "utilities/theme/_opacity.less"; @import "utilities/typography/_text-decoration.less"; @import "utilities/typography/_white-space.less"; +@import "utilities/typography/_word-break.less"; @import "utilities/_flexbox.less"; @import "utilities/_spacing.less"; @import "utilities/_text-align.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_word-break.less b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_word-break.less new file mode 100644 index 0000000000..e9e8017330 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_word-break.less @@ -0,0 +1,7 @@ +/* + WORD BREAK +*/ + +.word-normal { word-break: normal; } +.word-wrap { word-break: break-all; } +.word-nowrap { word-break: keep-all; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.controller.js index 6b8462b583..e179e0acb3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.controller.js @@ -123,11 +123,14 @@ oldProperty.isObject = true; } - // create new property object used in the diff table + // diff requires a string + property.value = property.value ? property.value : ""; + oldProperty.value = oldProperty.value ? oldProperty.value : ""; + var diffProperty = { "alias": property.alias, "label": property.label, - "diff": (property.value || oldProperty.value) ? JsDiff.diffWords(property.value, oldProperty.value) : "", + "diff": JsDiff.diffWords(property.value, oldProperty.value), "isObject": (property.isObject || oldProperty.isObject) ? true : false }; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.html index f7ab78b7a0..b5b925b266 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/rollback/rollback.html @@ -63,7 +63,7 @@ {{property.label}} - + {{part.value}} {{part.value}} From 9f557d56979012143080e8d82c1cd924f11236a7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 13:03:43 +0100 Subject: [PATCH 50/60] fix color picker model.value --- .../views/propertyeditors/colorpicker/colorpicker.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html index c86e7f44f7..ef45e99638 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html @@ -5,10 +5,11 @@ You haven't defined any colors
- + From 45feb9577de81d6a1614a16122902f91e3a7b78d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 13:30:37 +0100 Subject: [PATCH 51/60] get spectrum color picker from npm + get latest version --- src/Umbraco.Web.UI.Client/gulpfile.js | 8 + .../lib/spectrum/spectrum.css | 519 ------------------ .../lib/spectrum/spectrum.js | 9 - src/Umbraco.Web.UI.Client/package.json | 3 +- 4 files changed, 10 insertions(+), 529 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.css delete mode 100644 src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.js diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index f9d21c701a..7c23682349 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -334,6 +334,14 @@ gulp.task('dependencies', function () { "src": ["./node_modules/signalr/jquery.signalR.js"], "base": "./node_modules/signalr" }, + { + "name": "spectrum", + "src": [ + "./node_modules/spectrum-colorpicker/spectrum.js", + "./node_modules/spectrum-colorpicker/spectrum.css" + ], + "base": "./node_modules/spectrum-colorpicker" + }, { "name": "tinymce", "src": [ diff --git a/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.css b/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.css deleted file mode 100644 index 9e8d111c4d..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.css +++ /dev/null @@ -1,519 +0,0 @@ -/*** -Spectrum Colorpicker v1.3.3 -https://github.com/bgrins/spectrum -Author: Brian Grinstead -License: MIT -***/ - -.sp-container { - position:absolute; - top:0; - left:0; - display:inline-block; - *display: inline; - *zoom: 1; - /* https://github.com/bgrins/spectrum/issues/40 */ - z-index: 9999994; - overflow: hidden; -} -.sp-container.sp-flat { - position: relative; -} - -/* Fix for * { box-sizing: border-box; } */ -.sp-container, -.sp-container * { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ -.sp-top { - position:relative; - width: 100%; - display:inline-block; -} -.sp-top-inner { - position:absolute; - top:0; - left:0; - bottom:0; - right:0; -} -.sp-color { - position: absolute; - top:0; - left:0; - bottom:0; - right:20%; -} -.sp-hue { - position: absolute; - top:0; - right:0; - bottom:0; - left:84%; - height: 100%; -} - -.sp-clear-enabled .sp-hue { - top:33px; - height: 77.5%; -} - -.sp-fill { - padding-top: 80%; -} -.sp-sat, .sp-val { - position: absolute; - top:0; - left:0; - right:0; - bottom:0; -} - -.sp-alpha-enabled .sp-top { - margin-bottom: 18px; -} -.sp-alpha-enabled .sp-alpha { - display: block; -} -.sp-alpha-handle { - position:absolute; - top:-4px; - bottom: -4px; - width: 6px; - left: 50%; - cursor: pointer; - border: 1px solid black; - background: white; - opacity: .8; -} -.sp-alpha { - display: none; - position: absolute; - bottom: -14px; - right: 0; - left: 0; - height: 8px; -} -.sp-alpha-inner { - border: solid 1px #333; -} - -.sp-clear { - display: none; -} - -.sp-clear.sp-clear-display { - background-position: center; -} - -.sp-clear-enabled .sp-clear { - display: block; - position:absolute; - top:0px; - right:0; - bottom:0; - left:84%; - height: 28px; -} - -/* Don't allow text selection */ -.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { - -webkit-user-select:none; - -moz-user-select: -moz-none; - -o-user-select:none; - user-select: none; -} - -.sp-container.sp-input-disabled .sp-input-container { - display: none; -} -.sp-container.sp-buttons-disabled .sp-button-container { - display: none; -} -.sp-palette-only .sp-picker-container { - display: none; -} -.sp-palette-disabled .sp-palette-container { - display: none; -} - -.sp-initial-disabled .sp-initial { - display: none; -} - - -/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ -.sp-sat { - background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); - background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); - background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); - background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); - background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); - background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; - filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); -} -.sp-val { - background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); - background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); - background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); - background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); - background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); - background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; - filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); -} - -.sp-hue { - background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); - background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); - background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); - background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); - background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); -} - -/* IE filters do not support multiple color stops. - Generate 6 divs, line them up, and do two color gradients for each. - Yes, really. - */ -.sp-1 { - height:17%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); -} -.sp-2 { - height:16%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); -} -.sp-3 { - height:17%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); -} -.sp-4 { - height:17%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); -} -.sp-5 { - height:16%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); -} -.sp-6 { - height:17%; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); -} - -.sp-hidden { - display: none !important; -} - -/* Clearfix hack */ -.sp-cf:before, .sp-cf:after { content: ""; display: table; } -.sp-cf:after { clear: both; } -.sp-cf { *zoom: 1; } - -/* Mobile devices, make hue slider bigger so it is easier to slide */ -@media (max-device-width: 480px) { - .sp-color { right: 40%; } - .sp-hue { left: 63%; } - .sp-fill { padding-top: 60%; } -} -.sp-dragger { - border-radius: 5px; - height: 5px; - width: 5px; - border: 1px solid #fff; - background: #000; - cursor: pointer; - position:absolute; - top:0; - left: 0; -} -.sp-slider { - position: absolute; - top:0; - cursor:pointer; - height: 3px; - left: -1px; - right: -1px; - border: 1px solid #000; - background: white; - opacity: .8; -} - -/* -Theme authors: -Here are the basic themeable display options (colors, fonts, global widths). -See http://bgrins.github.io/spectrum/themes/ for instructions. -*/ - -.sp-container { - border-radius: 0; - background-color: #ECECEC; - border: solid 1px #f0c49B; - padding: 0; -} -.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear -{ - font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; -} -.sp-top -{ - margin-bottom: 3px; -} -.sp-color, .sp-hue, .sp-clear -{ - border: solid 1px #666; -} - -/* Input */ -.sp-input-container { - float:right; - width: 100px; - margin-bottom: 4px; -} -.sp-initial-disabled .sp-input-container { - width: 100%; -} -.sp-input { - font-size: 12px !important; - border: 1px inset; - padding: 4px 5px; - margin: 0; - width: 100%; - background:transparent; - border-radius: 3px; - color: #222; -} -.sp-input:focus { - border: 1px solid orange; -} -.sp-input.sp-validation-error -{ - border: 1px solid red; - background: #fdd; -} -.sp-picker-container , .sp-palette-container -{ - float:left; - position: relative; - padding: 10px; - padding-bottom: 300px; - margin-bottom: -290px; -} -.sp-picker-container -{ - width: 172px; - border-left: solid 1px #fff; -} - -/* Palettes */ -.sp-palette-container -{ - border-right: solid 1px #ccc; -} - -.sp-palette .sp-thumb-el { - display: block; - position:relative; - float:left; - width: 24px; - height: 15px; - margin: 3px; - cursor: pointer; - border:solid 2px transparent; -} -.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { - border-color: orange; -} -.sp-thumb-el -{ - position:relative; -} - -/* Initial */ -.sp-initial -{ - float: left; - border: solid 1px #333; -} -.sp-initial span { - width: 30px; - height: 25px; - border:none; - display:block; - float:left; - margin:0; -} - -.sp-initial .sp-clear-display { - background-position: center; -} - -/* Buttons */ -.sp-button-container { - float: right; -} - -/* Replacer (the little preview div that shows up instead of the ) */ -.sp-replacer { - margin:0; - overflow:hidden; - cursor:pointer; - padding: 4px; - display:inline-block; - *zoom: 1; - *display: inline; - border: solid 1px #91765d; - background: #eee; - color: #333; - vertical-align: middle; -} -.sp-replacer:hover, .sp-replacer.sp-active { - border-color: #F0C49B; - color: #111; -} -.sp-replacer.sp-disabled { - cursor:default; - border-color: silver; - color: silver; -} -.sp-dd { - padding: 2px 0; - height: 16px; - line-height: 16px; - float:left; - font-size:10px; -} -.sp-preview -{ - position:relative; - width:25px; - height: 20px; - border: solid 1px #222; - margin-right: 5px; - float:left; - z-index: 0; -} - -.sp-palette -{ - *width: 220px; - max-width: 220px; -} -.sp-palette .sp-thumb-el -{ - width:16px; - height: 16px; - margin:2px 1px; - border: solid 1px #d0d0d0; -} - -.sp-container -{ - padding-bottom:0; -} - - -/* Buttons: http://hellohappy.org/css3-buttons/ */ -.sp-container button { - background-color: #eeeeee; - background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); - background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); - background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); - background-image: -o-linear-gradient(top, #eeeeee, #cccccc); - background-image: linear-gradient(to bottom, #eeeeee, #cccccc); - border: 1px solid #ccc; - border-bottom: 1px solid #bbb; - border-radius: 3px; - color: #333; - font-size: 14px; - line-height: 1; - padding: 5px 4px; - text-align: center; - text-shadow: 0 1px 0 #eee; - vertical-align: middle; -} -.sp-container button:hover { - background-color: #dddddd; - background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); - background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); - background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); - background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); - background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); - border: 1px solid #bbb; - border-bottom: 1px solid #999; - cursor: pointer; - text-shadow: 0 1px 0 #ddd; -} -.sp-container button:active { - border: 1px solid #aaa; - border-bottom: 1px solid #888; - -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; - -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; - -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; - -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; - box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; -} -.sp-cancel -{ - font-size: 11px; - color: #d93f3f !important; - margin:0; - padding:2px; - margin-right: 5px; - vertical-align: middle; - text-decoration:none; - -} -.sp-cancel:hover -{ - color: #d93f3f !important; - text-decoration: underline; -} - - -.sp-palette span:hover, .sp-palette span.sp-thumb-active -{ - border-color: #000; -} - -.sp-preview, .sp-alpha, .sp-thumb-el -{ - position:relative; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); -} -.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner -{ - display:block; - position:absolute; - top:0;left:0;bottom:0;right:0; -} - -.sp-palette .sp-thumb-inner -{ - background-position: 50% 50%; - background-repeat: no-repeat; -} - -.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner -{ - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); -} - -.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner -{ - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); -} - -.sp-clear-display { - background-repeat:no-repeat; - background-position: center; - background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); -} diff --git a/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.js b/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.js deleted file mode 100644 index 629a050341..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/spectrum/spectrum.js +++ /dev/null @@ -1,9 +0,0 @@ -!function (window, $, undefined) { - function paletteTemplate(p, color, className) { for (var html = [], i = 0; i < p.length; i++) { var current = p[i]; if (current) { var tiny = tinycolor(current), c = tiny.toHsl().l < .5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light"; c += tinycolor.equals(color, current) ? " sp-thumb-active" : ""; var swatchStyle = rgbaSupport ? "background-color:" + tiny.toRgbString() : "filter:" + tiny.toFilter(); html.push('') } else { var cls = "sp-clear-display"; html.push('') } } return "
" + html.join("") + "
" } function hideAll() { for (var i = 0; i < spectrums.length; i++) spectrums[i] && spectrums[i].hide() } function instanceOptions(o, callbackContext) { var opts = $.extend({}, defaultOpts, o); return opts.callbacks = { move: bind(opts.move, callbackContext), change: bind(opts.change, callbackContext), show: bind(opts.show, callbackContext), hide: bind(opts.hide, callbackContext), beforeShow: bind(opts.beforeShow, callbackContext) }, opts } function spectrum(element, o) { function applyOptions() { if (opts.showPaletteOnly && (opts.showPalette = !0), opts.palette) { palette = opts.palette.slice(0), paletteArray = $.isArray(palette[0]) ? palette : [palette], paletteLookup = {}; for (var i = 0; i < paletteArray.length; i++) for (var j = 0; j < paletteArray[i].length; j++) { var rgb = tinycolor(paletteArray[i][j]).toRgbString(); paletteLookup[rgb] = !0 } } container.toggleClass("sp-flat", flat), container.toggleClass("sp-input-disabled", !opts.showInput), container.toggleClass("sp-alpha-enabled", opts.showAlpha), container.toggleClass("sp-clear-enabled", allowEmpty), container.toggleClass("sp-buttons-disabled", !opts.showButtons), container.toggleClass("sp-palette-disabled", !opts.showPalette), container.toggleClass("sp-palette-only", opts.showPaletteOnly), container.toggleClass("sp-initial-disabled", !opts.showInitial), container.addClass(opts.className), reflow() } function initialize() { function palletElementClick(e) { return e.data && e.data.ignore ? (set($(this).data("color")), move()) : (set($(this).data("color")), move(), updateOriginalInput(!0), hide()), !1 } if (IE && container.find("*:not(input)").attr("unselectable", "on"), applyOptions(), shouldReplace && boundElement.after(replacer).hide(), allowEmpty || clearButton.hide(), flat) boundElement.after(container).hide(); else { var appendTo = "parent" === opts.appendTo ? boundElement.parent() : $(opts.appendTo); 1 !== appendTo.length && (appendTo = $("body")), appendTo.append(container) } updateSelectionPaletteFromStorage(), offsetElement.bind("click.spectrum touchstart.spectrum", function (e) { disabled || toggle(), e.stopPropagation(), $(e.target).is("input") || e.preventDefault() }), (boundElement.is(":disabled") || opts.disabled === !0) && disable(), container.click(stopPropagation), textInput.change(setFromTextInput), textInput.bind("paste", function () { setTimeout(setFromTextInput, 1) }), textInput.keydown(function (e) { 13 == e.keyCode && setFromTextInput() }), cancelButton.text(opts.cancelText), cancelButton.bind("click.spectrum", function (e) { e.stopPropagation(), e.preventDefault(), hide("cancel") }), clearButton.attr("title", opts.clearText), clearButton.bind("click.spectrum", function (e) { e.stopPropagation(), e.preventDefault(), isEmpty = !0, move(), flat && updateOriginalInput(!0) }), chooseButton.text(opts.chooseText), chooseButton.bind("click.spectrum", function (e) { e.stopPropagation(), e.preventDefault(), isValid() && (updateOriginalInput(!0), hide()) }), draggable(alphaSlider, function (dragX, dragY, e) { currentAlpha = dragX / alphaWidth, isEmpty = !1, e.shiftKey && (currentAlpha = Math.round(10 * currentAlpha) / 10), move() }, dragStart, dragStop), draggable(slider, function (dragX, dragY) { currentHue = parseFloat(dragY / slideHeight), isEmpty = !1, opts.showAlpha || (currentAlpha = 1), move() }, dragStart, dragStop), draggable(dragger, function (dragX, dragY, e) { if (e.shiftKey) { if (!shiftMovementDirection) { var oldDragX = currentSaturation * dragWidth, oldDragY = dragHeight - currentValue * dragHeight, furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY); shiftMovementDirection = furtherFromX ? "x" : "y" } } else shiftMovementDirection = null; var setSaturation = !shiftMovementDirection || "x" === shiftMovementDirection, setValue = !shiftMovementDirection || "y" === shiftMovementDirection; setSaturation && (currentSaturation = parseFloat(dragX / dragWidth)), setValue && (currentValue = parseFloat((dragHeight - dragY) / dragHeight)), isEmpty = !1, opts.showAlpha || (currentAlpha = 1), move() }, dragStart, dragStop), initialColor ? (set(initialColor), updateUI(), currentPreferredFormat = preferredFormat || tinycolor(initialColor).format, addColorToSelectionPalette(initialColor)) : updateUI(), flat && show(); var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum"; paletteContainer.delegate(".sp-thumb-el", paletteEvent, palletElementClick), initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: !0 }, palletElementClick) } function updateSelectionPaletteFromStorage() { if (localStorageKey && window.localStorage) { try { var oldPalette = window.localStorage[localStorageKey].split(",#"); oldPalette.length > 1 && (delete window.localStorage[localStorageKey], $.each(oldPalette, function (i, c) { addColorToSelectionPalette(c) })) } catch (e) { } try { selectionPalette = window.localStorage[localStorageKey].split(";") } catch (e) { } } } function addColorToSelectionPalette(color) { if (showSelectionPalette) { var rgb = tinycolor(color).toRgbString(); if (!paletteLookup[rgb] && -1 === $.inArray(rgb, selectionPalette)) for (selectionPalette.push(rgb) ; selectionPalette.length > maxSelectionSize;) selectionPalette.shift(); if (localStorageKey && window.localStorage) try { window.localStorage[localStorageKey] = selectionPalette.join(";") } catch (e) { } } } function getUniqueSelectionPalette() { var unique = []; if (opts.showPalette) for (i = 0; i < selectionPalette.length; i++) { var rgb = tinycolor(selectionPalette[i]).toRgbString(); paletteLookup[rgb] || unique.push(selectionPalette[i]) } return unique.reverse().slice(0, opts.maxSelectionSize) } function drawPalette() { var currentColor = get(), html = $.map(paletteArray, function (palette, i) { return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i) }); updateSelectionPaletteFromStorage(), selectionPalette && html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection")), paletteContainer.html(html.join("")) } function drawInitial() { if (opts.showInitial) { var initial = colorOnShow, current = get(); initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial")) } } function dragStart() { (0 >= dragHeight || 0 >= dragWidth || 0 >= slideHeight) && reflow(), container.addClass(draggingClass), shiftMovementDirection = null, boundElement.trigger("dragstart.spectrum", [get()]) } function dragStop() { container.removeClass(draggingClass), boundElement.trigger("dragstop.spectrum", [get()]) } function setFromTextInput() { var value = textInput.val(); if (null !== value && "" !== value || !allowEmpty) { var tiny = tinycolor(value); tiny.ok ? (set(tiny), updateOriginalInput(!0)) : textInput.addClass("sp-validation-error") } else set(null), updateOriginalInput(!0) } function toggle() { visible ? hide() : show() } function show() { var event = $.Event("beforeShow.spectrum"); return visible ? void reflow() : (boundElement.trigger(event, [get()]), void (callbacks.beforeShow(get()) === !1 || event.isDefaultPrevented() || (hideAll(), visible = !0, $(doc).bind("click.spectrum", hide), $(window).bind("resize.spectrum", resize), replacer.addClass("sp-active"), container.removeClass("sp-hidden"), reflow(), updateUI(), colorOnShow = get(), drawInitial(), callbacks.show(colorOnShow), boundElement.trigger("show.spectrum", [colorOnShow])))) } function hide(e) { if ((!e || "click" != e.type || 2 != e.button) && visible && !flat) { visible = !1, $(doc).unbind("click.spectrum", hide), $(window).unbind("resize.spectrum", resize), replacer.removeClass("sp-active"), container.addClass("sp-hidden"); var colorHasChanged = !tinycolor.equals(get(), colorOnShow); colorHasChanged && (clickoutFiresChange && "cancel" !== e ? updateOriginalInput(!0) : revert()), callbacks.hide(get()), boundElement.trigger("hide.spectrum", [get()]) } } function revert() { set(colorOnShow, !0) } function set(color, ignoreFormatChange) { if (tinycolor.equals(color, get())) return void updateUI(); var newColor, newHsv; !color && allowEmpty ? isEmpty = !0 : (isEmpty = !1, newColor = tinycolor(color), newHsv = newColor.toHsv(), currentHue = newHsv.h % 360 / 360, currentSaturation = newHsv.s, currentValue = newHsv.v, currentAlpha = newHsv.a), updateUI(), newColor && newColor.ok && !ignoreFormatChange && (currentPreferredFormat = preferredFormat || newColor.format) } function get(opts) { return opts = opts || {}, allowEmpty && isEmpty ? null : tinycolor.fromRatio({ h: currentHue, s: currentSaturation, v: currentValue, a: Math.round(100 * currentAlpha) / 100 }, { format: opts.format || currentPreferredFormat }) } function isValid() { return !textInput.hasClass("sp-validation-error") } function move() { updateUI(), callbacks.move(get()), boundElement.trigger("move.spectrum", [get()]) } function updateUI() { textInput.removeClass("sp-validation-error"), updateHelperLocations(); var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 }); dragger.css("background-color", flatColor.toHexString()); var format = currentPreferredFormat; 1 > currentAlpha && (0 !== currentAlpha || "name" !== format) && ("hex" === format || "hex3" === format || "hex6" === format || "name" === format) && (format = "rgb"); var realColor = get({ format: format }), displayColor = ""; if (previewElement.removeClass("sp-clear-display"), previewElement.css("background-color", "transparent"), !realColor && allowEmpty) previewElement.addClass("sp-clear-display"); else { var realHex = realColor.toHexString(), realRgb = realColor.toRgbString(); if (rgbaSupport || 1 === realColor.alpha ? previewElement.css("background-color", realRgb) : (previewElement.css("background-color", "transparent"), previewElement.css("filter", realColor.toFilter())), opts.showAlpha) { var rgb = realColor.toRgb(); rgb.a = 0; var realAlpha = tinycolor(rgb).toRgbString(), gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")"; IE ? alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex)) : (alphaSliderInner.css("background", "-webkit-" + gradient), alphaSliderInner.css("background", "-moz-" + gradient), alphaSliderInner.css("background", "-ms-" + gradient), alphaSliderInner.css("background", "linear-gradient(to right, " + realAlpha + ", " + realHex + ")")) } displayColor = realColor.toString(format) } opts.showInput && textInput.val(displayColor), opts.showPalette && drawPalette(), drawInitial() } function updateHelperLocations() { var s = currentSaturation, v = currentValue; if (allowEmpty && isEmpty) alphaSlideHelper.hide(), slideHelper.hide(), dragHelper.hide(); else { alphaSlideHelper.show(), slideHelper.show(), dragHelper.show(); var dragX = s * dragWidth, dragY = dragHeight - v * dragHeight; dragX = Math.max(-dragHelperHeight, Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)), dragY = Math.max(-dragHelperHeight, Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)), dragHelper.css({ top: dragY + "px", left: dragX + "px" }); var alphaX = currentAlpha * alphaWidth; alphaSlideHelper.css({ left: alphaX - alphaSlideHelperWidth / 2 + "px" }); var slideY = currentHue * slideHeight; slideHelper.css({ top: slideY - slideHelperHeight + "px" }) } } function updateOriginalInput(fireCallback) { var color = get(), displayColor = "", hasChanged = !tinycolor.equals(color, colorOnShow); color && (displayColor = color.toString(currentPreferredFormat), addColorToSelectionPalette(color)), isInput && boundElement.val(displayColor), colorOnShow = color, fireCallback && hasChanged && (callbacks.change(color), boundElement.trigger("change", [color])) } function reflow() { dragWidth = dragger.width(), dragHeight = dragger.height(), dragHelperHeight = dragHelper.height(), slideWidth = slider.width(), slideHeight = slider.height(), slideHelperHeight = slideHelper.height(), alphaWidth = alphaSlider.width(), alphaSlideHelperWidth = alphaSlideHelper.width(), flat || (container.css("position", "absolute"), container.offset(getOffset(container, offsetElement))), updateHelperLocations(), opts.showPalette && drawPalette(), boundElement.trigger("reflow.spectrum") } function destroy() { boundElement.show(), offsetElement.unbind("click.spectrum touchstart.spectrum"), container.remove(), replacer.remove(), spectrums[spect.id] = null } function option(optionName, optionValue) { return optionName === undefined ? $.extend({}, opts) : optionValue === undefined ? opts[optionName] : (opts[optionName] = optionValue, void applyOptions()) } function enable() { disabled = !1, boundElement.attr("disabled", !1), offsetElement.removeClass("sp-disabled") } function disable() { hide(), disabled = !0, boundElement.attr("disabled", !0), offsetElement.addClass("sp-disabled") } var opts = instanceOptions(o, element), flat = opts.flat, showSelectionPalette = opts.showSelectionPalette, localStorageKey = opts.localStorageKey, theme = opts.theme, callbacks = opts.callbacks, resize = throttle(reflow, 10), visible = !1, dragWidth = 0, dragHeight = 0, dragHelperHeight = 0, slideHeight = 0, slideWidth = 0, alphaWidth = 0, alphaSlideHelperWidth = 0, slideHelperHeight = 0, currentHue = 0, currentSaturation = 0, currentValue = 0, currentAlpha = 1, palette = [], paletteArray = [], paletteLookup = {}, selectionPalette = opts.selectionPalette.slice(0), maxSelectionSize = opts.maxSelectionSize, draggingClass = "sp-dragging", shiftMovementDirection = null, doc = element.ownerDocument, boundElement = (doc.body, $(element)), disabled = !1, container = $(markup, doc).addClass(theme), dragger = container.find(".sp-color"), dragHelper = container.find(".sp-dragger"), slider = container.find(".sp-hue"), slideHelper = container.find(".sp-slider"), alphaSliderInner = container.find(".sp-alpha-inner"), alphaSlider = container.find(".sp-alpha"), alphaSlideHelper = container.find(".sp-alpha-handle"), textInput = container.find(".sp-input"), paletteContainer = container.find(".sp-palette"), initialColorContainer = container.find(".sp-initial"), cancelButton = container.find(".sp-cancel"), clearButton = container.find(".sp-clear"), chooseButton = container.find(".sp-choose"), isInput = boundElement.is("input"), isInputTypeColor = isInput && inputTypeColorSupport && "color" === boundElement.attr("type"), shouldReplace = isInput && !flat, replacer = shouldReplace ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]), offsetElement = shouldReplace ? replacer : boundElement, previewElement = replacer.find(".sp-preview-inner"), initialColor = opts.color || isInput && boundElement.val(), colorOnShow = !1, preferredFormat = opts.preferredFormat, currentPreferredFormat = preferredFormat, clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange, isEmpty = !initialColor, allowEmpty = opts.allowEmpty && !isInputTypeColor; initialize(); var spect = { show: show, hide: hide, toggle: toggle, reflow: reflow, option: option, enable: enable, disable: disable, set: function (c) { set(c), updateOriginalInput() }, get: get, destroy: destroy, container: container }; return spect.id = spectrums.push(spect) - 1, spect } function getOffset(picker, input) { var extraY = 0, dpWidth = picker.outerWidth(), dpHeight = picker.outerHeight(), inputHeight = input.outerHeight(), doc = picker[0].ownerDocument, docElem = doc.documentElement, viewWidth = docElem.clientWidth + $(doc).scrollLeft(), viewHeight = docElem.clientHeight + $(doc).scrollTop(), offset = input.offset(); return offset.top += inputHeight, offset.left -= Math.min(offset.left, offset.left + dpWidth > viewWidth && viewWidth > dpWidth ? Math.abs(offset.left + dpWidth - viewWidth) : 0), offset.top -= Math.min(offset.top, offset.top + dpHeight > viewHeight && viewHeight > dpHeight ? Math.abs(dpHeight + inputHeight - extraY) : extraY), offset } function noop() { } function stopPropagation(e) { e.stopPropagation() } function bind(func, obj) { var slice = Array.prototype.slice, args = slice.call(arguments, 2); return function () { return func.apply(obj, args.concat(slice.call(arguments))) } } function draggable(element, onmove, onstart, onstop) { function prevent(e) { e.stopPropagation && e.stopPropagation(), e.preventDefault && e.preventDefault(), e.returnValue = !1 } function move(e) { if (dragging) { if (IE && document.documentMode < 9 && !e.button) return stop(); var touches = e.originalEvent.touches, pageX = touches ? touches[0].pageX : e.pageX, pageY = touches ? touches[0].pageY : e.pageY, dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth)), dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight)); hasTouch && prevent(e), onmove.apply(element, [dragX, dragY, e]) } } function start(e) { { var rightclick = e.which ? 3 == e.which : 2 == e.button; e.originalEvent.touches } rightclick || dragging || onstart.apply(element, arguments) !== !1 && (dragging = !0, maxHeight = $(element).height(), maxWidth = $(element).width(), offset = $(element).offset(), $(doc).bind(duringDragEvents), $(doc.body).addClass("sp-dragging"), hasTouch || move(e), prevent(e)) } function stop() { dragging && ($(doc).unbind(duringDragEvents), $(doc.body).removeClass("sp-dragging"), onstop.apply(element, arguments)), dragging = !1 } onmove = onmove || function () { }, onstart = onstart || function () { }, onstop = onstop || function () { }; var doc = element.ownerDocument || document, dragging = !1, offset = {}, maxHeight = 0, maxWidth = 0, hasTouch = "ontouchstart" in window, duringDragEvents = {}; duringDragEvents.selectstart = prevent, duringDragEvents.dragstart = prevent, duringDragEvents["touchmove mousemove"] = move, duringDragEvents["touchend mouseup"] = stop, $(element).bind("touchstart mousedown", start) } function throttle(func, wait, debounce) { var timeout; return function () { var context = this, args = arguments, throttler = function () { timeout = null, func.apply(context, args) }; debounce && clearTimeout(timeout), (debounce || !timeout) && (timeout = setTimeout(throttler, wait)) } } var defaultOpts = { beforeShow: noop, move: noop, change: noop, show: noop, hide: noop, color: !1, flat: !1, showInput: !1, allowEmpty: !1, showButtons: !0, clickoutFiresChange: !1, showInitial: !1, showPalette: !1, showPaletteOnly: !1, showSelectionPalette: !0, localStorageKey: !1, appendTo: "body", maxSelectionSize: 7, cancelText: "cancel", chooseText: "choose", clearText: "Clear Color Selection", preferredFormat: !1, className: "", showAlpha: !1, theme: "sp-light", palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]], selectionPalette: [], disabled: !1 }, spectrums = [], IE = !!/msie/i.exec(window.navigator.userAgent), rgbaSupport = function () { function contains(str, substr) { return !!~("" + str).indexOf(substr) } var elem = document.createElement("div"), style = elem.style; return style.cssText = "background-color:rgba(0,0,0,.5)", contains(style.backgroundColor, "rgba") || contains(style.backgroundColor, "hsla") }(), inputTypeColorSupport = function () { var colorInput = $("")[0]; return "color" === colorInput.type && "!" !== colorInput.value }(), replaceInput = ["
", "
", "
", "
"].join(""), markup = function () { var gradientFix = ""; if (IE) for (var i = 1; 6 >= i; i++) gradientFix += "
"; return ["
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", "
", gradientFix, "
", "
", "
", "
", "
", "", "
", "
", "
", "", "", "
", "
", "
"].join("") }(), dataID = "spectrum.id"; $.fn.spectrum = function (opts) { if ("string" == typeof opts) { var returnValue = this, args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var spect = spectrums[$(this).data(dataID)]; if (spect) { var method = spect[opts]; if (!method) throw new Error("Spectrum: no such method: '" + opts + "'"); "get" == opts ? returnValue = spect.get() : "container" == opts ? returnValue = spect.container : "option" == opts ? returnValue = spect.option.apply(spect, args) : "destroy" == opts ? (spect.destroy(), $(this).removeData(dataID)) : method.apply(spect, args) } }), returnValue } return this.spectrum("destroy").each(function () { var options = $.extend({}, opts, $(this).data()), spect = spectrum(this, options); $(this).data(dataID, spect.id) }) }, $.fn.spectrum.load = !0, $.fn.spectrum.loadOpts = {}, $.fn.spectrum.draggable = draggable, $.fn.spectrum.defaults = defaultOpts, $.spectrum = {}, $.spectrum.localization = {}, $.spectrum.palettes = {}, $.fn.spectrum.processNativeColorInputs = function () { inputTypeColorSupport || $("input[type=color]").spectrum({ preferredFormat: "hex6" }) }, function () { - function tinycolor(color, opts) { if (color = color ? color : "", opts = opts || {}, "object" == typeof color && color.hasOwnProperty("_tc_id")) return color; var rgb = inputToRGB(color), r = rgb.r, g = rgb.g, b = rgb.b, a = rgb.a, roundA = mathRound(100 * a) / 100, format = opts.format || rgb.format; return 1 > r && (r = mathRound(r)), 1 > g && (g = mathRound(g)), 1 > b && (b = mathRound(b)), { ok: rgb.ok, format: format, _tc_id: tinyCounter++, alpha: a, getAlpha: function () { return a }, setAlpha: function (value) { a = boundAlpha(value), roundA = mathRound(100 * a) / 100 }, toHsv: function () { var hsv = rgbToHsv(r, g, b); return { h: 360 * hsv.h, s: hsv.s, v: hsv.v, a: a } }, toHsvString: function () { var hsv = rgbToHsv(r, g, b), h = mathRound(360 * hsv.h), s = mathRound(100 * hsv.s), v = mathRound(100 * hsv.v); return 1 == a ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, " + roundA + ")" }, toHsl: function () { var hsl = rgbToHsl(r, g, b); return { h: 360 * hsl.h, s: hsl.s, l: hsl.l, a: a } }, toHslString: function () { var hsl = rgbToHsl(r, g, b), h = mathRound(360 * hsl.h), s = mathRound(100 * hsl.s), l = mathRound(100 * hsl.l); return 1 == a ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, " + roundA + ")" }, toHex: function (allow3Char) { return rgbToHex(r, g, b, allow3Char) }, toHexString: function (allow3Char) { return "#" + this.toHex(allow3Char) }, toHex8: function () { return rgbaToHex(r, g, b, a) }, toHex8String: function () { return "#" + this.toHex8() }, toRgb: function () { return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a } }, toRgbString: function () { return 1 == a ? "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" : "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")" }, toPercentageRgb: function () { return { r: mathRound(100 * bound01(r, 255)) + "%", g: mathRound(100 * bound01(g, 255)) + "%", b: mathRound(100 * bound01(b, 255)) + "%", a: a } }, toPercentageRgbString: function () { return 1 == a ? "rgb(" + mathRound(100 * bound01(r, 255)) + "%, " + mathRound(100 * bound01(g, 255)) + "%, " + mathRound(100 * bound01(b, 255)) + "%)" : "rgba(" + mathRound(100 * bound01(r, 255)) + "%, " + mathRound(100 * bound01(g, 255)) + "%, " + mathRound(100 * bound01(b, 255)) + "%, " + roundA + ")" }, toName: function () { return 0 === a ? "transparent" : hexNames[rgbToHex(r, g, b, !0)] || !1 }, toFilter: function (secondColor) { var hex8String = "#" + rgbaToHex(r, g, b, a), secondHex8String = hex8String, gradientType = opts && opts.gradientType ? "GradientType = 1, " : ""; if (secondColor) { var s = tinycolor(secondColor); secondHex8String = s.toHex8String() } return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")" }, toString: function (format) { var formatSet = !!format; format = format || this.format; var formattedString = !1, hasAlphaAndFormatNotSet = !formatSet && 1 > a && a > 0, formatWithAlpha = hasAlphaAndFormatNotSet && ("hex" === format || "hex6" === format || "hex3" === format || "name" === format); return "rgb" === format && (formattedString = this.toRgbString()), "prgb" === format && (formattedString = this.toPercentageRgbString()), ("hex" === format || "hex6" === format) && (formattedString = this.toHexString()), "hex3" === format && (formattedString = this.toHexString(!0)), "hex8" === format && (formattedString = this.toHex8String()), "name" === format && (formattedString = this.toName()), "hsl" === format && (formattedString = this.toHslString()), "hsv" === format && (formattedString = this.toHsvString()), formatWithAlpha ? this.toRgbString() : formattedString || this.toHexString() } } } function inputToRGB(color) { var rgb = { r: 0, g: 0, b: 0 }, a = 1, ok = !1, format = !1; return "string" == typeof color && (color = stringInputToObject(color)), "object" == typeof color && (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b") ? (rgb = rgbToRgb(color.r, color.g, color.b), ok = !0, format = "%" === String(color.r).substr(-1) ? "prgb" : "rgb") : color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v") ? (color.s = convertToPercentage(color.s), color.v = convertToPercentage(color.v), rgb = hsvToRgb(color.h, color.s, color.v), ok = !0, format = "hsv") : color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l") && (color.s = convertToPercentage(color.s), color.l = convertToPercentage(color.l), rgb = hslToRgb(color.h, color.s, color.l), ok = !0, format = "hsl"), color.hasOwnProperty("a") && (a = color.a)), a = boundAlpha(a), { ok: ok, format: color.format || format, r: mathMin(255, mathMax(rgb.r, 0)), g: mathMin(255, mathMax(rgb.g, 0)), b: mathMin(255, mathMax(rgb.b, 0)), a: a } } function rgbToRgb(r, g, b) { return { r: 255 * bound01(r, 255), g: 255 * bound01(g, 255), b: 255 * bound01(b, 255) } } function rgbToHsl(r, g, b) { r = bound01(r, 255), g = bound01(g, 255), b = bound01(b, 255); var h, s, max = mathMax(r, g, b), min = mathMin(r, g, b), l = (max + min) / 2; if (max == min) h = s = 0; else { var d = max - min; switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) { case r: h = (g - b) / d + (b > g ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4 } h /= 6 } return { h: h, s: s, l: l } } function hslToRgb(h, s, l) { function hue2rgb(p, q, t) { return 0 > t && (t += 1), t > 1 && (t -= 1), 1 / 6 > t ? p + 6 * (q - p) * t : .5 > t ? q : 2 / 3 > t ? p + (q - p) * (2 / 3 - t) * 6 : p } var r, g, b; if (h = bound01(h, 360), s = bound01(s, 100), l = bound01(l, 100), 0 === s) r = g = b = l; else { var q = .5 > l ? l * (1 + s) : l + s - l * s, p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3), g = hue2rgb(p, q, h), b = hue2rgb(p, q, h - 1 / 3) } return { r: 255 * r, g: 255 * g, b: 255 * b } } function rgbToHsv(r, g, b) { r = bound01(r, 255), g = bound01(g, 255), b = bound01(b, 255); var h, s, max = mathMax(r, g, b), min = mathMin(r, g, b), v = max, d = max - min; if (s = 0 === max ? 0 : d / max, max == min) h = 0; else { switch (max) { case r: h = (g - b) / d + (b > g ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4 } h /= 6 } return { h: h, s: s, v: v } } function hsvToRgb(h, s, v) { h = 6 * bound01(h, 360), s = bound01(s, 100), v = bound01(v, 100); var i = math.floor(h), f = h - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s), mod = i % 6, r = [v, q, p, p, t, v][mod], g = [t, v, v, q, p, p][mod], b = [p, p, t, v, v, q][mod]; return { r: 255 * r, g: 255 * g, b: 255 * b } } function rgbToHex(r, g, b, allow3Char) { var hex = [pad2(mathRound(r).toString(16)), pad2(mathRound(g).toString(16)), pad2(mathRound(b).toString(16))]; return allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) ? hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) : hex.join("") } function rgbaToHex(r, g, b, a) { var hex = [pad2(convertDecimalToHex(a)), pad2(mathRound(r).toString(16)), pad2(mathRound(g).toString(16)), pad2(mathRound(b).toString(16))]; return hex.join("") } function flip(o) { var flipped = {}; for (var i in o) o.hasOwnProperty(i) && (flipped[o[i]] = i); return flipped } function boundAlpha(a) { return a = parseFloat(a), (isNaN(a) || 0 > a || a > 1) && (a = 1), a } function bound01(n, max) { isOnePointZero(n) && (n = "100%"); var processPercent = isPercentage(n); return n = mathMin(max, mathMax(0, parseFloat(n))), processPercent && (n = parseInt(n * max, 10) / 100), math.abs(n - max) < 1e-6 ? 1 : n % max / parseFloat(max) } function clamp01(val) { return mathMin(1, mathMax(0, val)) } function parseIntFromHex(val) { return parseInt(val, 16) } function isOnePointZero(n) { return "string" == typeof n && -1 != n.indexOf(".") && 1 === parseFloat(n) } function isPercentage(n) { return "string" == typeof n && -1 != n.indexOf("%") } function pad2(c) { return 1 == c.length ? "0" + c : "" + c } function convertToPercentage(n) { return 1 >= n && (n = 100 * n + "%"), n } function convertDecimalToHex(d) { return Math.round(255 * parseFloat(d)).toString(16) } function convertHexToDecimal(h) { return parseIntFromHex(h) / 255 } function stringInputToObject(color) { color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase(); var named = !1; if (names[color]) color = names[color], named = !0; else if ("transparent" == color) return { r: 0, g: 0, b: 0, a: 0, format: "name" }; var match; return (match = matchers.rgb.exec(color)) ? { r: match[1], g: match[2], b: match[3] } : (match = matchers.rgba.exec(color)) ? { r: match[1], g: match[2], b: match[3], a: match[4] } : (match = matchers.hsl.exec(color)) ? { h: match[1], s: match[2], l: match[3] } : (match = matchers.hsla.exec(color)) ? { h: match[1], s: match[2], l: match[3], a: match[4] } : (match = matchers.hsv.exec(color)) ? { h: match[1], s: match[2], v: match[3] } : (match = matchers.hex8.exec(color)) ? { a: convertHexToDecimal(match[1]), r: parseIntFromHex(match[2]), g: parseIntFromHex(match[3]), b: parseIntFromHex(match[4]), format: named ? "name" : "hex8" } : (match = matchers.hex6.exec(color)) ? { r: parseIntFromHex(match[1]), g: parseIntFromHex(match[2]), b: parseIntFromHex(match[3]), format: named ? "name" : "hex" } : (match = matchers.hex3.exec(color)) ? { r: parseIntFromHex(match[1] + "" + match[1]), g: parseIntFromHex(match[2] + "" + match[2]), b: parseIntFromHex(match[3] + "" + match[3]), format: named ? "name" : "hex" } : !1 } var trimLeft = /^[\s,#]+/, trimRight = /\s+$/, tinyCounter = 0, math = Math, mathRound = math.round, mathMin = math.min, mathMax = math.max, mathRandom = math.random; tinycolor.fromRatio = function (color, opts) { if ("object" == typeof color) { var newColor = {}; for (var i in color) color.hasOwnProperty(i) && (newColor[i] = "a" === i ? color[i] : convertToPercentage(color[i])); color = newColor } return tinycolor(color, opts) }, tinycolor.equals = function (color1, color2) { return color1 && color2 ? tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString() : !1 }, tinycolor.random = function () { return tinycolor.fromRatio({ r: mathRandom(), g: mathRandom(), b: mathRandom() }) }, tinycolor.desaturate = function (color, amount) { amount = 0 === amount ? 0 : amount || 10; var hsl = tinycolor(color).toHsl(); return hsl.s -= amount / 100, hsl.s = clamp01(hsl.s), tinycolor(hsl) }, tinycolor.saturate = function (color, amount) { amount = 0 === amount ? 0 : amount || 10; var hsl = tinycolor(color).toHsl(); return hsl.s += amount / 100, hsl.s = clamp01(hsl.s), tinycolor(hsl) }, tinycolor.greyscale = function (color) { return tinycolor.desaturate(color, 100) }, tinycolor.lighten = function (color, amount) { amount = 0 === amount ? 0 : amount || 10; var hsl = tinycolor(color).toHsl(); return hsl.l += amount / 100, hsl.l = clamp01(hsl.l), tinycolor(hsl) }, tinycolor.darken = function (color, amount) { amount = 0 === amount ? 0 : amount || 10; var hsl = tinycolor(color).toHsl(); return hsl.l -= amount / 100, hsl.l = clamp01(hsl.l), tinycolor(hsl) }, tinycolor.complement = function (color) { var hsl = tinycolor(color).toHsl(); return hsl.h = (hsl.h + 180) % 360, tinycolor(hsl) }, tinycolor.triad = function (color) { var hsl = tinycolor(color).toHsl(), h = hsl.h; return [tinycolor(color), tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })] }, tinycolor.tetrad = function (color) { var hsl = tinycolor(color).toHsl(), h = hsl.h; return [tinycolor(color), tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })] }, tinycolor.splitcomplement = function (color) { var hsl = tinycolor(color).toHsl(), h = hsl.h; return [tinycolor(color), tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l })] }, tinycolor.analogous = function (color, results, slices) { results = results || 6, slices = slices || 30; var hsl = tinycolor(color).toHsl(), part = 360 / slices, ret = [tinycolor(color)]; for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) hsl.h = (hsl.h + part) % 360, ret.push(tinycolor(hsl)); return ret }, tinycolor.monochromatic = function (color, results) { results = results || 6; for (var hsv = tinycolor(color).toHsv(), h = hsv.h, s = hsv.s, v = hsv.v, ret = [], modification = 1 / results; results--;) ret.push(tinycolor({ h: h, s: s, v: v })), v = (v + modification) % 1; return ret }, tinycolor.readability = function (color1, color2) { var a = tinycolor(color1).toRgb(), b = tinycolor(color2).toRgb(), brightnessA = (299 * a.r + 587 * a.g + 114 * a.b) / 1e3, brightnessB = (299 * b.r + 587 * b.g + 114 * b.b) / 1e3, colorDiff = Math.max(a.r, b.r) - Math.min(a.r, b.r) + Math.max(a.g, b.g) - Math.min(a.g, b.g) + Math.max(a.b, b.b) - Math.min(a.b, b.b); return { brightness: Math.abs(brightnessA - brightnessB), color: colorDiff } }, tinycolor.readable = function (color1, color2) { var readability = tinycolor.readability(color1, color2); return readability.brightness > 125 && readability.color > 500 }, tinycolor.mostReadable = function (baseColor, colorList) { - for (var bestColor = null, bestScore = 0, bestIsReadable = !1, i = 0; i < colorList.length; i++) { - var readability = tinycolor.readability(baseColor, colorList[i]), readable = readability.brightness > 125 && readability.color > 500, score = 3 * (readability.brightness / 125) + readability.color / 500; (readable && !bestIsReadable || readable && bestIsReadable && score > bestScore || !readable && !bestIsReadable && score > bestScore) && (bestIsReadable = readable, bestScore = score, bestColor = tinycolor(colorList[i])) - } return bestColor - }; var names = tinycolor.names = { aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "0ff", aquamarine: "7fffd4", azure: "f0ffff", beige: "f5f5dc", bisque: "ffe4c4", black: "000", blanchedalmond: "ffebcd", blue: "00f", blueviolet: "8a2be2", brown: "a52a2a", burlywood: "deb887", burntsienna: "ea7e5d", cadetblue: "5f9ea0", chartreuse: "7fff00", chocolate: "d2691e", coral: "ff7f50", cornflowerblue: "6495ed", cornsilk: "fff8dc", crimson: "dc143c", cyan: "0ff", darkblue: "00008b", darkcyan: "008b8b", darkgoldenrod: "b8860b", darkgray: "a9a9a9", darkgreen: "006400", darkgrey: "a9a9a9", darkkhaki: "bdb76b", darkmagenta: "8b008b", darkolivegreen: "556b2f", darkorange: "ff8c00", darkorchid: "9932cc", darkred: "8b0000", darksalmon: "e9967a", darkseagreen: "8fbc8f", darkslateblue: "483d8b", darkslategray: "2f4f4f", darkslategrey: "2f4f4f", darkturquoise: "00ced1", darkviolet: "9400d3", deeppink: "ff1493", deepskyblue: "00bfff", dimgray: "696969", dimgrey: "696969", dodgerblue: "1e90ff", firebrick: "b22222", floralwhite: "fffaf0", forestgreen: "228b22", fuchsia: "f0f", gainsboro: "dcdcdc", ghostwhite: "f8f8ff", gold: "ffd700", goldenrod: "daa520", gray: "808080", green: "008000", greenyellow: "adff2f", grey: "808080", honeydew: "f0fff0", hotpink: "ff69b4", indianred: "cd5c5c", indigo: "4b0082", ivory: "fffff0", khaki: "f0e68c", lavender: "e6e6fa", lavenderblush: "fff0f5", lawngreen: "7cfc00", lemonchiffon: "fffacd", lightblue: "add8e6", lightcoral: "f08080", lightcyan: "e0ffff", lightgoldenrodyellow: "fafad2", lightgray: "d3d3d3", lightgreen: "90ee90", lightgrey: "d3d3d3", lightpink: "ffb6c1", lightsalmon: "ffa07a", lightseagreen: "20b2aa", lightskyblue: "87cefa", lightslategray: "789", lightslategrey: "789", lightsteelblue: "b0c4de", lightyellow: "ffffe0", lime: "0f0", limegreen: "32cd32", linen: "faf0e6", magenta: "f0f", maroon: "800000", mediumaquamarine: "66cdaa", mediumblue: "0000cd", mediumorchid: "ba55d3", mediumpurple: "9370db", mediumseagreen: "3cb371", mediumslateblue: "7b68ee", mediumspringgreen: "00fa9a", mediumturquoise: "48d1cc", mediumvioletred: "c71585", midnightblue: "191970", mintcream: "f5fffa", mistyrose: "ffe4e1", moccasin: "ffe4b5", navajowhite: "ffdead", navy: "000080", oldlace: "fdf5e6", olive: "808000", olivedrab: "6b8e23", orange: "ffa500", orangered: "ff4500", orchid: "da70d6", palegoldenrod: "eee8aa", palegreen: "98fb98", paleturquoise: "afeeee", palevioletred: "db7093", papayawhip: "ffefd5", peachpuff: "ffdab9", peru: "cd853f", pink: "ffc0cb", plum: "dda0dd", powderblue: "b0e0e6", purple: "800080", red: "f00", rosybrown: "bc8f8f", royalblue: "4169e1", saddlebrown: "8b4513", salmon: "fa8072", sandybrown: "f4a460", seagreen: "2e8b57", seashell: "fff5ee", sienna: "a0522d", silver: "c0c0c0", skyblue: "87ceeb", slateblue: "6a5acd", slategray: "708090", slategrey: "708090", snow: "fffafa", springgreen: "00ff7f", steelblue: "4682b4", tan: "d2b48c", teal: "008080", thistle: "d8bfd8", tomato: "ff6347", turquoise: "40e0d0", violet: "ee82ee", wheat: "f5deb3", white: "fff", whitesmoke: "f5f5f5", yellow: "ff0", yellowgreen: "9acd32" }, hexNames = tinycolor.hexNames = flip(names), matchers = function () { var CSS_INTEGER = "[-\\+]?\\d+%?", CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?", CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")", PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?", PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; return { rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ } }(); window.tinycolor = tinycolor - }(), $(function () { $.fn.spectrum.load && $.fn.spectrum.processNativeColorInputs() }) -}(window, jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 66efdd97a8..a2870868f8 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -26,13 +26,14 @@ "font-awesome": "4.7.0", "jquery": "3.3.1", "jquery-ui-dist": "1.12.1", - "jquery-ui-touch-punch": "^0.2.3", + "jquery-ui-touch-punch": "0.2.3", "lazyload-js": "1.0.0", "moment": "2.22.2", "ng-file-upload": "12.2.13", "nouislider": "12.1.0", "npm": "^6.4.1", "signalr": "2.4.0", + "spectrum-colorpicker": "1.8.0", "tinymce": "4.9.0", "typeahead.js": "0.11.1", "underscore": "1.9.1" From 3a839ca1effa9214d520c85404d03c00091c891d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 14:24:15 +0100 Subject: [PATCH 52/60] don't ship with moments libraries including locales --- src/Umbraco.Web.UI.Client/gulpfile.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 7c23682349..0af327d148 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -297,23 +297,14 @@ gulp.task('dependencies', function () { "src": ["./node_modules/lazyload-js/lazyload.min.js"], "base": "./node_modules/lazyload-js" }, - // TODO: We can optimize here: - // we don't have to ship with the moment-with-locales libraries - // we lazyload the user locale { "name": "moment", - "src": [ - "./node_modules/moment/min/moment.min.js", - "./node_modules/moment/min/moment-with-locales.js", - "./node_modules/moment/min/moment-with-locales.min.js" - ], + "src": ["./node_modules/moment/min/moment.min.js"], "base": "./node_modules/moment/min" }, { "name": "moment", - "src": [ - "./node_modules/moment/locale/*.js" - ], + "src": ["./node_modules/moment/locale/*.js"], "base": "./node_modules/moment/locale" }, { From 80afcb64e0cb57a3ae399cea7e8463ced03fd6a9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 29 Nov 2018 15:10:11 +0100 Subject: [PATCH 53/60] remove bootstrap javascript --- .../lib/bootstrap/js/bootstrap.2.3.2.js | 2284 ----------------- .../lib/bootstrap/js/bootstrap.2.3.2.min.js | 6 - src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 1 - 3 files changed, 2291 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/bootstrap/js/bootstrap.2.3.2.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/bootstrap/js/bootstrap.2.3.2.min.js diff --git a/src/Umbraco.Web.UI.Client/lib/bootstrap/js/bootstrap.2.3.2.js b/src/Umbraco.Web.UI.Client/lib/bootstrap/js/bootstrap.2.3.2.js deleted file mode 100644 index 31701ad5df..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/bootstrap/js/bootstrap.2.3.2.js +++ /dev/null @@ -1,2284 +0,0 @@ -/* =================================================== - * bootstrap-transition.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#transitions - * =================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) - * ======================================================= */ - - $(function () { - - $.support.transition = (function () { - - var transitionEnd = (function () { - - var el = document.createElement('bootstrap') - , transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd' - , 'MozTransition' : 'transitionend' - , 'OTransition' : 'oTransitionEnd otransitionend' - , 'transition' : 'transitionend' - } - , name - - for (name in transEndEventNames){ - if (el.style[name] !== undefined) { - return transEndEventNames[name] - } - } - - }()) - - return transitionEnd && { - end: transitionEnd - } - - })() - - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-alert.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#alerts - * ========================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* ALERT CLASS DEFINITION - * ====================== */ - - var dismiss = '[data-dismiss="alert"]' - , Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - , selector = $this.attr('data-target') - , $parent - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = $(selector) - - e && e.preventDefault() - - $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) - - $parent.trigger(e = $.Event('close')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent - .trigger('closed') - .remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent.on($.support.transition.end, removeElement) : - removeElement() - } - - - /* ALERT PLUGIN DEFINITION - * ======================= */ - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('alert') - if (!data) $this.data('alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - /* ALERT NO CONFLICT - * ================= */ - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - /* ALERT DATA-API - * ============== */ - - $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) - -}(window.jQuery);/* ============================================================ - * bootstrap-button.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#buttons - * ============================================================ - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* BUTTON PUBLIC CLASS DEFINITION - * ============================== */ - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.button.defaults, options) - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - , $el = this.$element - , data = $el.data() - , val = $el.is('input') ? 'val' : 'html' - - state = state + 'Text' - data.resetText || $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d) - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.closest('[data-toggle="buttons-radio"]') - - $parent && $parent - .find('.active') - .removeClass('active') - - this.$element.toggleClass('active') - } - - - /* BUTTON PLUGIN DEFINITION - * ======================== */ - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('button') - , options = typeof option == 'object' && option - if (!data) $this.data('button', (data = new Button(this, options))) - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.defaults = { - loadingText: 'loading...' - } - - $.fn.button.Constructor = Button - - - /* BUTTON NO CONFLICT - * ================== */ - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - /* BUTTON DATA-API - * =============== */ - - $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-carousel.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#carousel - * ========================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CAROUSEL CLASS DEFINITION - * ========================= */ - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.prototype = { - - cycle: function (e) { - if (!e) this.paused = false - if (this.interval) clearInterval(this.interval); - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - return this - } - - , getActiveIndex: function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - return this.$items.index(this.$active) - } - - , to: function (pos) { - var activeIndex = this.getActiveIndex() - , that = this - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) { - return this.$element.one('slid', function () { - that.to(pos) - }) - } - - if (activeIndex == pos) { - return this.pause().cycle() - } - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - , pause: function (e) { - if (!e) this.paused = true - if (this.$element.find('.next, .prev').length && $.support.transition.end) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - clearInterval(this.interval) - this.interval = null - return this - } - - , next: function () { - if (this.sliding) return - return this.slide('next') - } - - , prev: function () { - if (this.sliding) return - return this.slide('prev') - } - - , slide: function (type, next) { - var $active = this.$element.find('.item.active') - , $next = next || $active[type]() - , isCycling = this.interval - , direction = type == 'next' ? 'left' : 'right' - , fallback = type == 'next' ? 'first' : 'last' - , that = this - , e - - this.sliding = true - - isCycling && this.pause() - - $next = $next.length ? $next : this.$element.find('.item')[fallback]() - - e = $.Event('slide', { - relatedTarget: $next[0] - , direction: direction - }) - - if ($next.hasClass('active')) return - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - this.$element.one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid') }, 0) - }) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid') - } - - isCycling && this.cycle() - - return this - } - - } - - - /* CAROUSEL PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('carousel') - , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) - , action = typeof option == 'string' ? option : options.slide - if (!data) $this.data('carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.defaults = { - interval: 5000 - , pause: 'hover' - } - - $.fn.carousel.Constructor = Carousel - - - /* CAROUSEL NO CONFLICT - * ==================== */ - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - /* CAROUSEL DATA-API - * ================= */ - - $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - , options = $.extend({}, $target.data(), $this.data()) - , slideIndex - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('carousel').pause().to(slideIndex).cycle() - } - - e.preventDefault() - }) - -}(window.jQuery);/* ============================================================= - * bootstrap-collapse.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#collapse - * ============================================================= - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* COLLAPSE PUBLIC CLASS DEFINITION - * ================================ */ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options.parent) { - this.$parent = $(this.options.parent) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension - , scroll - , actives - , hasData - - if (this.transitioning || this.$element.hasClass('in')) return - - dimension = this.dimension() - scroll = $.camelCase(['scroll', dimension].join('-')) - actives = this.$parent && this.$parent.find('> .accordion-group > .in') - - if (actives && actives.length) { - hasData = actives.data('collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', $.Event('show'), 'shown') - $.support.transition && this.$element[dimension](this.$element[0][scroll]) - } - - , hide: function () { - var dimension - if (this.transitioning || !this.$element.hasClass('in')) return - dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', $.Event('hide'), 'hidden') - this.$element[dimension](0) - } - - , reset: function (size) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function (method, startEvent, completeEvent) { - var that = this - , complete = function () { - if (startEvent.type == 'show') that.reset() - that.transitioning = 0 - that.$element.trigger(completeEvent) - } - - this.$element.trigger(startEvent) - - if (startEvent.isDefaultPrevented()) return - - this.transitioning = 1 - - this.$element[method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* COLLAPSE PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSE NO CONFLICT - * ==================== */ - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - /* COLLAPSE DATA-API - * ================= */ - - $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - $(target).collapse(option) - }) - -}(window.jQuery);/* ============================================================ - * bootstrap-dropdown.js v2.3.2 - * http://getbootstrap.com/2.3.2/javascript.html#dropdowns - * ============================================================ - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* DROPDOWN CLASS DEFINITION - * ========================= */ - - var toggle = '[data-toggle=dropdown]' - , Dropdown = function (element) { - var $el = $(element).on('click.dropdown.data-api', this.toggle) - $('html').on('click.dropdown.data-api', function () { - $el.parent().removeClass('open') - }) - } - - Dropdown.prototype = { - - constructor: Dropdown - - , toggle: function (e) { - var $this = $(this) - , $parent - , isActive - - if ($this.is('.disabled, :disabled')) return - - $parent = getParent($this) - - isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement) { - // if mobile we we use a backdrop because click events don't delegate - $('