binding): The model where the alias is bound.
@param {string} aliasFrom (binding): The model to generate the alias from.
+@param {string} validationPosition (binding): The position of the validation. Set to 'left' or 'right'.
@param {boolean=} enableLock (binding): Set to true to add a lock next to the alias from where it can be unlocked and changed.
**/
@@ -57,6 +58,7 @@ angular.module("umbraco.directives")
alias: '=',
aliasFrom: '=',
enableLock: '=?',
+ validationPosition: '=?',
serverValidationField: '@'
},
link: function (scope, element, attrs, ctrl) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umblockedfield.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umblockedfield.directive.js
index cc5a1eb2b1..f19e2c810b 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umblockedfield.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umblockedfield.directive.js
@@ -40,6 +40,7 @@ Use this directive to render a value with a lock next to it. When the lock is cl
@param {boolean=} locked (binding): true by default. Set to false to unlock the text.
@param {string=} placeholderText (binding): If ngModel is empty this text will be shown.
@param {string=} regexValidation (binding): Set a regex expression for validation of the field.
+@param {string} validationPosition (binding): The position of the validation. Set to 'left' or 'right'.
@param {string=} serverValidationField (attribute): Set a server validation field.
**/
@@ -70,7 +71,11 @@ Use this directive to render a value with a lock next to it. When the lock is cl
// if locked state is not defined as an attr set default state
if (scope.placeholderText === undefined || scope.placeholderText === null) {
scope.placeholderText = "Enter value...";
- }
+ }
+
+ if (scope.validationPosition === undefined || scope.validationPosition === null) {
+ scope.validationPosition = "left";
+ }
}
@@ -93,9 +98,10 @@ Use this directive to render a value with a lock next to it. When the lock is cl
templateUrl: 'views/components/umb-locked-field.html',
scope: {
ngModel: "=",
- locked: "=?",
+ locked: "=?",
placeholderText: "=?",
- regexValidation: "=?",
+ regexValidation: "=?",
+ validationPosition: "=?",
serverValidationField: "@"
},
link: link
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.mocks.js
index 9724c222b6..6bc7855528 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.mocks.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/tree.mocks.js
@@ -11,24 +11,24 @@ angular.module('umbraco.mocks').
var menu = [
{ name: "Create", cssclass: "plus", alias: "create", metaData: {} },
- { seperator: true, name: "Delete", cssclass: "remove", alias: "delete", metaData: {} },
+ { separator: true, name: "Delete", cssclass: "remove", alias: "delete", metaData: {} },
{ name: "Move", cssclass: "move", alias: "move", metaData: {} },
{ name: "Copy", cssclass: "copy", alias: "copy", metaData: {} },
{ name: "Sort", cssclass: "sort", alias: "sort", metaData: {} },
- { seperator: true, name: "Publish", cssclass: "globe", alias: "publish", metaData: {} },
+ { separator: true, name: "Publish", cssclass: "globe", alias: "publish", metaData: {} },
{ name: "Rollback", cssclass: "undo", alias: "rollback", metaData: {} },
- { seperator: true, name: "Permissions", cssclass: "lock", alias: "permissions", metaData: {} },
+ { separator: true, name: "Permissions", cssclass: "lock", alias: "permissions", metaData: {} },
{ name: "Audit Trail", cssclass: "time", alias: "audittrail", metaData: {} },
{ name: "Notifications", cssclass: "envelope", alias: "notifications", metaData: {} },
- { seperator: true, name: "Hostnames", cssclass: "home", alias: "hostnames", metaData: {} },
+ { separator: true, name: "Hostnames", cssclass: "home", alias: "hostnames", metaData: {} },
{ name: "Public Access", cssclass: "group", alias: "publicaccess", metaData: {} },
- { seperator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} },
+ { separator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} },
- { seperator: true, name: "Empty Recycle Bin", cssclass: "trash", alias: "emptyrecyclebin", metaData: {} }
+ { separator: true, name: "Empty Recycle Bin", cssclass: "trash", alias: "emptyrecyclebin", metaData: {} }
];
var result = {
@@ -94,7 +94,7 @@ angular.module('umbraco.mocks').
jsAction: "umbracoMenuActions.CreateChildEntity"
}
},
- { seperator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} }
+ { separator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} }
];
return [200, menu, null];
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
index ec1175ab6c..5c74971593 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
@@ -640,7 +640,7 @@ angular.module('umbraco.mocks').
"templateEditor_urlEncodeHelp": "Will format special characters in URLs",
"templateEditor_usedIfAllEmpty": "Will only be used when the field values above are empty",
"templateEditor_usedIfEmpty": "This field will only be used if the primary field is empty",
- "templateEditor_withTime": "Yes, with time. Seperator: ",
+ "templateEditor_withTime": "Yes, with time. Separator: ",
"translation_details": "Translation details",
"translation_DownloadXmlDTD": "Download xml DTD",
"translation_fields": "Fields",
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
index 47e5a24180..1258ec4099 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
@@ -421,7 +421,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
*/
reBindChangedProperties: function (origContent, savedContent) {
- //TODO: We should probably split out this logic to deal with media/members seperately to content
+ //TODO: We should probably split out this logic to deal with media/members separately to content
//a method to ignore built-in prop changes
var shouldIgnore = function (propName) {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
index 4705b8cc3e..bd493cf0d3 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less
@@ -125,6 +125,8 @@ body.touch .umb-tree {
position: inherit;
display: inherit;
+ list-style: none;
+
h6 {
padding: 10px 0 10px 20px;
font-weight: inherit;
@@ -137,7 +139,15 @@ body.touch .umb-tree {
}
&-item {
- padding-left: 20px;
+ padding: 4px 0;
+
+ &:hover {
+ background-color: @gray-10;
+ }
+
+ &-link {
+ display: block;
+ }
}
&-link {
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
index 0cb7bc9fe4..ba04069c6b 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
@@ -28,7 +28,7 @@
color: @black;
}
-.umb-breadcrumbs__seperator {
+.umb-breadcrumbs__separator {
position: relative;
top: 1px;
margin-left: 5px;
@@ -41,4 +41,4 @@ input.umb-breadcrumbs__add-ancestor {
margin-top: -2px;
margin-left: 3px;
width: 100px;
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-locked-field.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-locked-field.less
index 9001f1d473..8d9ae86ce7 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-locked-field.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-locked-field.less
@@ -38,6 +38,7 @@ input.umb-locked-field__input {
transition: color 0.25s;
padding: 0;
height: auto;
+ max-width: 300px;
}
input.umb-locked-field__input:focus {
diff --git a/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less b/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
index 417447c3dc..9b4bac723b 100644
--- a/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
+++ b/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
@@ -1,46 +1,67 @@
.umb-validation-label {
- position: absolute;
- top: 27px;
- width: 200px;
- padding: 1px 5px;
- background: @red;
- color: @white;
- font-size: 11px;
- line-height: 1.5em;
+ position: absolute;
+ top: 27px;
+ min-width: 100px;
+ max-width: 200px;
+ padding: 1px 5px;
+ background: @red;
+ color: @white;
+ font-size: 11px;
+ line-height: 1.5em;
}
.umb-validation-label:after {
- bottom: 100%;
- left: 10px;
- border: solid transparent;
- content: " ";
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- border-color: rgba(255, 255, 255, 0);
- border-bottom-color: @red;
- border-width: 4px;
- margin-left: -4px;
+ bottom: 100%;
+ left: 10px;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ border-color: rgba(255, 255, 255, 0);
+ border-bottom-color: @red;
+ border-width: 4px;
+ margin-left: -4px;
+}
+
+.umb-validation-label.-left {
+ left: 0;
+ right: auto;
+
+ &:after {
+ left: 10px;
+ right: auto;
+ }
+}
+
+.umb-validation-label.-right {
+ right: 0;
+ left: auto;
+
+ &:after {
+ right: 10px;
+ left: auto;
+ }
}
.umb-validation-label.-arrow-left {
- margin-left: 10px;
+ margin-left: 10px;
}
.umb-validation-label.-arrow-left:after {
- right: 100%;
- top: 50%;
- left: auto;
- bottom: auto;
- border: solid transparent;
- content: " ";
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- border-color: rgba(255, 255, 255, 0);
- border-right-color: @red;
- border-width: 4px;
- margin-top: -4px;
+ right: 100%;
+ top: 50%;
+ left: auto;
+ bottom: auto;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ border-color: rgba(255, 255, 255, 0);
+ border-right-color: @red;
+ border-width: 4px;
+ margin-top: -4px;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less
index 3d9df196d7..ae930d6fb0 100644
--- a/src/Umbraco.Web.UI.Client/src/less/panel.less
+++ b/src/Umbraco.Web.UI.Client/src/less/panel.less
@@ -373,10 +373,6 @@
margin-bottom: 0;
}
-.umb-panel-header-alias .umb-validation-label:after {
- visibility: hidden;
-}
-
.umb-panel-header-alias .umb-locked-field:after {
display: none;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js
index 81dfcfd5d3..7ae464d813 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js
@@ -33,31 +33,51 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
$scope.showTarget = $scope.model.hideTarget !== true;
+ // this ensures that we only sync the tree once and only when it's ready
+ var oneTimeTreeSync = {
+ executed: false,
+ treeReady: false,
+ sync: function () {
+ // don't run this if:
+ // - it was already run once
+ // - the tree isn't ready yet
+ // - the model path hasn't been loaded yet
+ if (this.executed || !this.treeReady || !($scope.model.target && $scope.model.target.path)) {
+ return;
+ }
+
+ this.executed = true;
+ // sync the tree to the model path
+ $scope.dialogTreeApi.syncTree({
+ path: $scope.model.target.path,
+ tree: "content"
+ });
+ }
+ };
+
if (dialogOptions.currentTarget) {
- $scope.model.target = dialogOptions.currentTarget;
+ // clone the current target so we don't accidentally update the caller's model while manipulating $scope.model.target
+ $scope.model.target = angular.copy(dialogOptions.currentTarget);
//if we have a node ID, we fetch the current node to build the form data
if ($scope.model.target.id || $scope.model.target.udi) {
//will be either a udi or an int
var id = $scope.model.target.udi ? $scope.model.target.udi : $scope.model.target.id;
- if (!$scope.model.target.path) {
-
+ // is it a content link?
+ if (!$scope.model.target.isMedia) {
+ // get the content path
entityResource.getPath(id, "Document").then(function (path) {
$scope.model.target.path = path;
- //now sync the tree to this path
- $scope.dialogTreeApi.syncTree({
- path: $scope.model.target.path,
- tree: "content"
- });
+ oneTimeTreeSync.sync();
+ });
+
+ // get the content properties to build the anchor name list
+ contentResource.getById(id).then(function (resp) {
+ $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
+ $scope.model.target.url = resp.urls[0];
});
}
-
- // if a link exists, get the properties to build the anchor name list
- contentResource.getById(id).then(function (resp) {
- $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties));
- $scope.model.target.url = resp.urls[0];
- });
} else if ($scope.model.target.url.length) {
// a url but no id/udi indicates an external link - trim the url to remove the anchor/qs
// only do the substring if there's a # or a ?
@@ -72,6 +92,11 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
$scope.anchorValues = dialogOptions.anchors;
}
+ function treeLoadedHandler(args) {
+ oneTimeTreeSync.treeReady = true;
+ oneTimeTreeSync.sync();
+ }
+
function nodeSelectHandler(args) {
if (args && args.event) {
args.event.preventDefault();
@@ -127,6 +152,12 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
$scope.model.target.url = mediaHelper.resolveFile(media);
editorService.close();
+
+ // make sure the content tree has nothing highlighted
+ $scope.dialogTreeApi.syncTree({
+ path: "-1",
+ tree: "content"
+ });
},
close: function() {
editorService.close();
@@ -146,7 +177,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
// method to select a search result
$scope.selectResult = function (evt, result) {
result.selected = result.selected === true ? false : true;
- nodeSelectHandler(evt, {
+ nodeSelectHandler({
event: evt,
node: result
});
@@ -159,6 +190,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
};
$scope.onTreeInit = function () {
+ $scope.dialogTreeApi.callbacks.treeLoaded(treeLoadedHandler);
$scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler);
$scope.dialogTreeApi.callbacks.treeNodeExpanded(nodeExpandedHandler);
}
@@ -166,7 +198,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController",
// Mini list view
$scope.selectListViewNode = function (node) {
node.selected = node.selected === true ? false : true;
- nodeSelectHandler({}, {
+ nodeSelectHandler({
node: node
});
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html
index cac412df8b..b5dd23b1fd 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html
@@ -55,12 +55,12 @@