From 8be303cb05d6100f5c47d5b128dfd7009132428d Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Sun, 17 Jun 2018 14:33:32 +1000 Subject: [PATCH 01/13] Adds key for 'anchor' to en variants. Needs translations. --- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 1 + src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 93d8e8b0f6..22596ff9dd 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -527,6 +527,7 @@ Add Alias All + Anchor Are you sure? Back Border 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 15256505a9..23d7f3698b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -526,6 +526,7 @@ Add Alias All + Anchor Are you sure? Back Border From f3375c01d8881181371978812792f4318fe0c16e Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Sun, 17 Jun 2018 14:38:37 +1000 Subject: [PATCH 02/13] remove unused dialog service, add logic for managing anchor value in link object, add function for parsing an array of anchors from a string --- .../src/common/services/tinymce.service.js | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 86de5b586d..d862789539 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -6,7 +6,7 @@ * @description * A service containing all logic for all of the Umbraco TinyMCE plugins */ -function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macroResource, macroService, $routeParams, umbRequestHelper, angularHelper, userService) { +function tinyMceService($log, imageHelper, $http, $timeout, macroResource, macroService, $routeParams, umbRequestHelper, angularHelper, userService) { return { /** @@ -645,6 +645,7 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; data.target = anchorElm ? dom.getAttrib(anchorElm, 'target') : ''; data.rel = anchorElm ? dom.getAttrib(anchorElm, 'rel') : ''; + data.anchor = anchorElm ? dom.getAttrib(anchorElm, 'anchor') : ''; if (selectedElm.nodeName === "IMG") { data.text = initialText = " "; @@ -677,8 +678,6 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro }; } - var injector = angular.element(document.getElementById("umbracoMainPageBody")).injector(); - var dialogService = injector.get("dialogService"); var currentTarget = null; //if we already have a link selected, we want to pass that data over to the dialog @@ -690,10 +689,20 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro target: anchor.attr("target") }; + // split the URL to check for an anchor or querystring, then add that value to the currentTarget object + var urlParts = currentTarget.url.split(/(\?|#)/); + if (urlParts.length === 3) { + currentTarget.anchor = urlParts[2]; + } + //locallink detection, we do this here, to avoid poluting the dialogservice //so the dialog service can just expect to get a node-like structure - if (currentTarget.url.indexOf("localLink:") > 0) { - var linkId = currentTarget.url.substring(currentTarget.url.indexOf(":") + 1, currentTarget.url.length - 1); + if (currentTarget.url.indexOf("localLink:") > 0) { + // if the current link has an anchor, it needs to be considered when getting the udi/id + // if an anchor exists, reduce the substring max by its length plus two to offset the removed prefix and trailing curly brace + var linkId = currentTarget.url.substring(currentTarget.url.indexOf(":") + 1, + currentTarget.url.length - (currentTarget.anchor ? currentTarget.anchor.length + 2 : 1)); + //we need to check if this is an INT or a UDI var parsedIntId = parseInt(linkId, 10); if (isNaN(parsedIntId)) { @@ -741,6 +750,20 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro }); }, + + getAnchorNames: function(propertyString) { + var anchorPattern = //gi; + var matches = propertyString.match(anchorPattern); + var anchors = []; + + if (matches) { + anchors = matches.map(function(v) { + return v.substring(v.indexOf('"') + 1, v.lastIndexOf('\\')); + }); + } + + return anchors; + }, insertLinkInEditor: function(editor, target, anchorElm) { @@ -749,13 +772,18 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro var hasUdi = target.udi ? true : false; var id = hasUdi ? target.udi : (target.id ? target.id : null); + // if an anchor exists, check that it is appropriately prefixed + if (target.anchor && target.anchor[0] !== '?' && target.anchor[0] !== '#') { + target.anchor = (target.anchor.indexOf('=') === -1 ? '#' : '?') + target.anchor; + } + //Create a json obj used to create the attributes for the tag function createElemAttributes() { var a = { href: href, title: target.name, target: target.target ? target.target : null, - rel: target.rel ? target.rel : null + rel: target.rel ? target.rel : null }; if (hasUdi) { a["data-udi"] = target.udi; @@ -763,6 +791,12 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro else if (target.id) { a["data-id"] = target.id; } + + if (target.anchor) { + a["data-anchor"] = target.anchor; + a.href = a.href + target.anchor; + } + return a; } From 1cbb456dcd61485af8705b5cc78715ce6f2ad965 Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Sun, 17 Jun 2018 14:39:45 +1000 Subject: [PATCH 03/13] update rte controllers to add anchors array to overlay model - anchors are parsed from the current editor properties --- .../src/views/propertyeditors/grid/editors/rte.controller.js | 4 +++- .../src/views/propertyeditors/rte/rte.controller.js | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/rte.controller.js index 99c3fd80ff..397438d5a0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/rte.controller.js @@ -1,7 +1,7 @@ (function() { "use strict"; - function GridRichTextEditorController($scope, tinyMceService, macroService) { + function GridRichTextEditorController($scope, tinyMceService, macroService, editorState) { var vm = this; @@ -11,9 +11,11 @@ vm.openEmbed = openEmbed; function openLinkPicker(editor, currentTarget, anchorElement) { + vm.linkPickerOverlay = { view: "linkpicker", currentTarget: currentTarget, + anchors: tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)), show: true, submit: function(model) { tinyMceService.insertLinkInEditor(editor, model.target, anchorElement); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js index 17f0f3b698..c5a739bec2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js @@ -1,6 +1,6 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.RTEController", - function ($rootScope, $scope, $q, $locale, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService) { + function ($rootScope, $scope, $q, $locale, dialogService, $log, imageHelper, assetsService, $timeout, tinyMceService, angularHelper, stylesheetResource, macroService, editorState) { $scope.isLoading = true; @@ -273,11 +273,12 @@ angular.module("umbraco") syncContent(editor); }); - + tinyMceService.createLinkPicker(editor, $scope, function(currentTarget, anchorElement) { $scope.linkPickerOverlay = { view: "linkpicker", currentTarget: currentTarget, + anchors: tinyMceService.getAnchorNames(JSON.stringify(editorState.current.properties)), show: true, submit: function(model) { tinyMceService.insertLinkInEditor(editor, model.target, anchorElement); From 3fecd55c49f5078212ccf3e18f0c5c3315c2e023 Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Sun, 17 Jun 2018 14:41:41 +1000 Subject: [PATCH 04/13] adds check for anchors when overlay opens, and fetches anchors when target updates. --- .../common/dialogs/linkpicker.controller.js | 13 +++++++---- .../linkpicker/linkpicker.controller.js | 23 +++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js index e76db90f47..ba6835a6b1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js @@ -1,6 +1,6 @@ //used for the media picker dialog angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController", - function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService) { + function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService, tinyMceService) { var dialogOptions = $scope.dialogOptions; var searchText = "Search..."; @@ -39,6 +39,10 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController", }); } } + + if (dialogOptions.anchors) { + $scope.anchorValues = dialogOptions.anchors; + } function nodeSelectHandler(ev, args) { args.event.preventDefault(); @@ -69,9 +73,10 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController", $scope.target.url = "/"; } else { - contentResource.getNiceUrl(args.node.id).then(function (url) { - $scope.target.url = url; - }); + contentResource.getById(args.node.id).then(function (resp) { + $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties)); + $scope.model.target.url = resp.urls[0]; + }); } if (!angular.isUndefined($scope.target.isMedia)) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js index 91c74311b3..5d6b0916f8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js @@ -1,8 +1,10 @@ //used for the media picker dialog angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", - function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService) { + function ($scope, eventsService, dialogService, entityResource, contentResource, mediaHelper, userService, localizationService, tinyMceService) { var dialogOptions = $scope.model; + var anchorPattern = //gi; + var searchText = "Search..."; localizationService.localize("general_search").then(function (value) { searchText = value + "..."; @@ -22,11 +24,10 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", selectedSearchResults: [] }; - $scope.showTarget = $scope.model.hideTarget !== true; + $scope.showTarget = $scope.model.hideTarget !== true; if (dialogOptions.currentTarget) { $scope.model.target = 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) { @@ -47,9 +48,12 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", }); } } - - function nodeSelectHandler(ev, args) { - + + if (dialogOptions.anchors) { + $scope.anchorValues = dialogOptions.anchors; + } + + function nodeSelectHandler(ev, args) { if(args && args.event) { args.event.preventDefault(); args.event.stopPropagation(); @@ -71,9 +75,10 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", if (args.node.id < 0) { $scope.model.target.url = "/"; } - else { - contentResource.getNiceUrl(args.node.id).then(function (url) { - $scope.model.target.url = url; + else { + contentResource.getById(args.node.id).then(function (resp) { + $scope.anchorValues = tinyMceService.getAnchorNames(JSON.stringify(resp.properties)); + $scope.model.target.url = resp.urls[0]; }); } From 9cfc997ba209780ac3e36f5b104cf33f8ff80ac2 Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Sun, 17 Jun 2018 14:42:16 +1000 Subject: [PATCH 05/13] update overlay/dialog to add input for anchor value - value can be a string or selection from the datalist. Is the dialog in use anymore? --- .../src/views/common/dialogs/linkpicker.html | 14 +++++++++++++- .../common/overlays/linkpicker/linkpicker.html | 15 ++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html index 442357edcc..0cc1c52595 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html @@ -2,13 +2,25 @@