diff --git a/src/Umbraco.Web.UI.Client/gruntFile.js b/src/Umbraco.Web.UI.Client/gruntFile.js index c765cba57d..c0b4665f16 100644 --- a/src/Umbraco.Web.UI.Client/gruntFile.js +++ b/src/Umbraco.Web.UI.Client/gruntFile.js @@ -228,7 +228,13 @@ module.exports = function (grunt) { noarg:true, sub:true, boss:true, - eqnull:true, + eqnull: true, + //NOTE: we need to use eval sometimes so ignore it + evil: true, + //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those + scripturl: true, + //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used + smarttabs: true, globals:{} } }, @@ -243,7 +249,13 @@ module.exports = function (grunt) { noarg:true, sub:true, boss:true, - eqnull:true, + eqnull: true, + //NOTE: we need to use eval sometimes so ignore it + evil: true, + //NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those + scripturl: true, + //NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used + smarttabs: true, globalstrict:true, globals:{$:false, jQuery:false,define:false,require:false,window:false} } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/umbpropertyinclude.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/umbpropertyinclude.directive.js deleted file mode 100644 index 38c10ef0d0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/directives/umbpropertyinclude.directive.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @ngdoc directive - * @name umbraco.directives:umbPropertyInclude - * - * @description - * This is a specialized version of ng-include (yes the code is borrowed). We need to know if the property editor - * contents requires a async JS call made before we compile. - * - * @restrict A - * @element ANY - * @param umbPropEditorHelper {umbPropEditorHelper} a utility class for dealing with property editors/paths - */ -function umbPropertyInclude($http, $templateCache, $anchorScroll, $compile, umbPropEditorHelper, scriptLoader) { - return { - restrict: "E", //restrict to element - terminal: true, - compile: function (element, attr) { - var srcExp = attr.src; - return function (scope, element, attr) { - var changeCounter = 0, - childScope; - - var clearContent = function () { - if (childScope) { - childScope.$destroy(); - childScope = null; - } - }; - - scope.$watch(srcExp, function (src) { - var thisChangeId = ++changeCounter; - - if (src) { - - //format to the correct source - var editorView = umbPropEditorHelper.getViewPath(src); - var isNonUmbraco = src.startsWith('/'); - - $http.get(editorView, { cache: $templateCache }).success(function (response) { - if (thisChangeId !== changeCounter){ - return; - } - - if (childScope) { - childScope.$destroy(); - } - childScope = scope.$new(); - - var contents = $('
').html(response).contents(); - - //before we compile, we need to check if we need to make a js call - //now we need to parse the contents to see if there's an ng-controller directive - if (isNonUmbraco && /ng-controller=["'][\w\.]+["']/.test(response)) { - //ok, there's a controller declared, we will assume there's javascript to go and get - - //get the js file which exists at ../Js/EditorName.js - var lastSlash = src.lastIndexOf("/"); - var fullViewName = src.substring(lastSlash + 1, src.length); - var viewName = fullViewName.indexOf(".") > 0 ? fullViewName.substring(0, fullViewName.indexOf(".")) : fullViewName; - var jsPath = scope.model.view.substring(0, lastSlash + 1) + "../Js/" + viewName + ".js"; - - scriptLoader.load([jsPath], scope).then(function () { - //the script loaded so load the view - element.html(contents); - $compile(contents)(childScope); - }); - } - else { - element.html(contents); - $compile(contents)(childScope); - } - }).error(function () { - if (thisChangeId === changeCounter){ - clearContent(); - } - }); - } else { - clearContent(); - } - }); - }; - } - }; -} - -angular.module('umbraco.directives').directive("umbPropertyInclude", umbPropertyInclude); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/umbtreeitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/umbtreeitem.directive.js index 282eb05ff7..22270d3c60 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/umbtreeitem.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/umbtreeitem.directive.js @@ -39,11 +39,12 @@ angular.module("umbraco.directives") scope.select = function(e,n,ev){ //here we need to check for some legacy tree code - if (n.jsClickCallback && n.jsClickCallback != "") { + if (n.jsClickCallback && n.jsClickCallback !== "") { //this is a legacy tree node! + var jsPrefix = "javascript:"; var js; - if (n.jsClickCallback.startsWith("javascript:")) { - js = n.jsClickCallback.substr("javascript:".length); + if (n.jsClickCallback.startsWith(jsPrefix)) { + js = n.jsClickCallback.substr(jsPrefix.length); } else { js = n.jsClickCallback; @@ -55,8 +56,8 @@ angular.module("umbraco.directives") func.call(); } } - catch(e) { - $log.error("Error evaluating js callback from legacy tree node: " + e); + catch(ex) { + $log.error("Error evaluating js callback from legacy tree node: " + ex); } } else { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js index 5493b2ec05..34499f3395 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js @@ -6,7 +6,7 @@ describing the state of the validation element. This is useful for parent elements to know about child element validation state. **/ -function valBubble(umbFormHelper) { +function valBubble(angularHelper) { return { require: 'ngModel', restrict: "A", @@ -16,7 +16,7 @@ function valBubble(umbFormHelper) { throw "valBubble must be set on an input element that has a 'name' attribute"; } - var currentForm = umbFormHelper.getCurrentForm(scope); + var currentForm = angularHelper.getCurrentForm(scope); if (!currentForm || !currentForm.$name){ throw "valBubble requires that a name is assigned to the ng-form containing the validated input"; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js index e8d92749a7..b7336d6575 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js @@ -4,7 +4,7 @@ * @restrict A * @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ? **/ -function valToggleMsg(umbFormHelper) { +function valToggleMsg(angularHelper) { return { restrict: "A", link: function (scope, element, attr, ctrl) { @@ -20,7 +20,7 @@ function valToggleMsg(umbFormHelper) { var showValidation = false; var hasError = false; - var currentForm = umbFormHelper.getCurrentForm(scope); + var currentForm = angularHelper.getCurrentForm(scope); if (!currentForm || !currentForm.$name){ throw "valToggleMsg requires that a name is assigned to the ng-form containing the validated input"; } 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 66bdfd76db..168e2764d2 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 @@ -143,12 +143,12 @@ angular.module('umbraco.services') this.ui.dialogTitle = args.action.name; var templateUrl = "views/" + this.ui.currentTree + "/" + args.action.alias + ".html"; - var d = dialogService.append( - { - container: $("#dialog div.umb-panel-body"), - scope: scope, - template: templateUrl - }); + var d = dialogService.append( + { + container: $("#dialog div.umb-panel-body"), + scope: scope, + template: templateUrl + }); }, hideDialog: function() { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js b/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js index e81cfe4566..cbcbb627b4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/utill.service.js @@ -21,8 +21,63 @@ function angularHelper() { * This checks if a digest/apply is already occuring, if not it will force an apply call */ safeApply: function (scope, fn) { - (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn); - } + if (scope.$$phase || scope.$root.$$phase) { + fn(); + } + else { + scope.$apply(fn); + } + }, + + /** + * @ngdoc function + * @name getCurrentForm + * @methodOf angularHelper + * @function + * + * @description + * Returns the current form object applied to the scope or null if one is not found + */ + getCurrentForm: function (scope) { + //NOTE: There isn't a way in angular to get a reference to the current form object since the form object + // is just defined as a property of the scope when it is named but you'll always need to know the name which + // isn't very convenient. If we want to watch for validation changes we need to get a form reference. + // The way that we detect the form object is a bit hackerific in that we detect all of the required properties + // that exist on a form object. + + var form = null; + var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"]; + + // a method to check that the collection of object prop names contains the property name expected + var propertyExists = function (objectPropNames) { + //ensure that every required property name exists on the current scope property + return _.every(requiredFormProps, function (item) { + return _.contains(objectPropNames, item); + }); + }; + + for (var p in scope) { + + if (_.isObject(scope[p]) && p.substr(0, 1) !== "$") { + //get the keys of the property names for the current property + var props = _.keys(scope[p]); + //if the length isn't correct, try the next prop + if (props.length < requiredFormProps.length) { + continue; + } + + //ensure that every required property name exists on the current scope property + var containProperty = propertyExists(props); + + if (containProperty) { + form = scope[p]; + break; + } + } + } + + return form; + } }; } angular.module('umbraco.services').factory('angularHelper', angularHelper); @@ -265,47 +320,6 @@ function umbDataFormatter() { } angular.module('umbraco.services').factory('umbDataFormatter', umbDataFormatter); -/** -* @ngdoc factory -* @name umbraco.services:umbFormHelper -* @description Returns the current form object applied to the scope or null if one is not found -**/ -function umbFormHelper() { - return { - getCurrentForm: function(scope) { - //NOTE: There isn't a way in angular to get a reference to the current form object since the form object - // is just defined as a property of the scope when it is named but you'll always need to know the name which - // isn't very convenient. If we want to watch for validation changes we need to get a form reference. - // The way that we detect the form object is a bit hackerific in that we detect all of the required properties - // that exist on a form object. - - var form = null; - var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"]; - - for (var p in scope) { - - if (_.isObject(scope[p]) && p.substr(0, 1) !== "$") { - var props = _.keys(scope[p]); - if (props.length < requiredFormProps.length){ - continue; - } - - /* - var containProperty = _.every(requiredFormProps, function(item){return _.contains(props, item);}); - - if (containProperty){ - form = scope[p]; - break; - }*/ - } - } - - return form; - } - }; -} -angular.module('umbraco.services').factory('umbFormHelper', umbFormHelper); - /** * @ngdoc factory * @name umbraco.services.tree:treeIconHelper diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/umb-property.html b/src/Umbraco.Web.UI.Client/src/views/directives/umb-property.html index 91e0c43fa4..18d71528fe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/umb-property.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/umb-property.html @@ -14,7 +14,7 @@
- +
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest index f7fbce24d6..509c2098e8 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Package.manifest @@ -37,6 +37,9 @@ } ], javascript: [ - '~/App_Plugins/MyPackage/Common/Js/MyPackage.js' + '~/App_Plugins/MyPackage/Common/Js/MyPackage.js', + '~/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js', + '~/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js', + '~/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js' ] } \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js index db076f635a..6ad8c7ab59 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/CsvEditor.js @@ -39,5 +39,5 @@ }, true); }; - angular.module("myPackage.controllers").controller('MyPackage.PropertyEditors.CsvEditorController', csvEditorController); + angular.module("umbraco").controller('MyPackage.PropertyEditors.CsvEditorController', csvEditorController); })(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js index 6ef140eaf5..93cd8d7654 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/PostcodeEditor.js @@ -7,6 +7,6 @@ $scope.model.config = { country: $scope.model.config[0] }; }; - angular.module("myPackage.controllers").controller('MyPackage.PropertyEditors.PostcodeEditor', postcodeEditor); + angular.module("umbraco").controller('MyPackage.PropertyEditors.PostcodeEditor', postcodeEditor); })(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js index 92839313a0..d691edcf6b 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Js/RegexEditor.js @@ -6,6 +6,6 @@ var asdf = ""; }; - angular.module("myPackage.controllers").controller('MyPackage.PropertyEditors.RegexEditor', regexEditor); + angular.module("umbraco").controller('MyPackage.PropertyEditors.RegexEditor', regexEditor); })(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/Views/directives/umb-property.html b/src/Umbraco.Web.UI/umbraco/Views/directives/umb-property.html index 91e0c43fa4..18d71528fe 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/directives/umb-property.html +++ b/src/Umbraco.Web.UI/umbraco/Views/directives/umb-property.html @@ -14,7 +14,7 @@
- +