diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbeditorbuttons.js b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbeditorbuttons.js new file mode 100644 index 0000000000..194f5a1fbf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbeditorbuttons.js @@ -0,0 +1,21 @@ +/** +* @ngdoc directive +* @name umbraco.directives.directive:umbEditorButtons +* @restrict E +* @function +* @description +* The button holder for editors (i.e. save, update, etc...) +**/ +angular.module("umbraco.directives") + .directive('umbEditorButtons', function () { + return { + require: "^umbTabs", + restrict: 'E', + transclude: true, + template: '
', + link: function(scope, element, attrs, ngModel) { + + + } + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbtabs.js b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbtabs.js new file mode 100644 index 0000000000..307eab4e0b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbtabs.js @@ -0,0 +1,82 @@ +/** +* @ngdoc directive +* @name umbraco.directives.directive:umbTabs +* @restrict E +* @function +* @description +* Used to control tab changes in editors, this directive must be placed around any editors' tabs (including header tabs and body tabs) +**/ +angular.module("umbraco.directives") + .directive('umbTabs', function() { + return { + //uses a controller to expose an API + controller: function ($scope, $attrs, $element, $parse) { + + //NOTE: This whole $parse strategy is the same type of thing used by ngModel, we need to use it + // because angular 1.1.5 is stupid. Normally we could just make a scope with =umbTags but that doesn't + // work for attribute type directives, seems to only work for element directives and I don't want this to + // be an element directive.... so we're using this. + var tabsValueGet = $parse($attrs.umbTabs); + + //internal props + + var activeTabId = null; + var tabCollectionChangedCallbacks = []; + var activeTabChangedCallbacks = []; + var firstRun = false; + var tabs = []; + + //public props/methods + + this.getActiveTab = function() { + return activeTabId; + }; + this.setActiveTab = function(tabId) { + activeTabId = tabId; + for (var callback in activeTabChangedCallbacks) { + activeTabChangedCallbacks[callback](activeTabId); + } + }; + this.onTabCollectionChanged = function (callback) { + tabCollectionChangedCallbacks.push(callback); + }; + this.onActiveTabChanged = function (callback) { + activeTabChangedCallbacks.push(callback); + }; + + $scope.$watch(function() { + return tabsValueGet($scope); + }, function (newValue, oldValue) { + if (newValue !== oldValue || (angular.isArray(newValue) && angular.isArray(oldValue) && newValue.length !== oldValue.length)) { + + tabs = []; //reset first + for (var val in newValue) { + var tab = { id: newValue[val].id, label: newValue[val].label }; + tabs.push(tab); + } + + //set active tab to the first one - one time + if (firstRun === false) { + firstRun = true; + if (tabs.length > 0) { + activeTabId = tabs[0].id; + for (var activeTabCallback in activeTabChangedCallbacks) { + activeTabChangedCallbacks[activeTabCallback](activeTabId); + } + } + } + + for (var callback in tabCollectionChangedCallbacks) { + tabCollectionChangedCallbacks[callback](tabs); + } + } + }); + + $scope.$on('$destroy', function () { + tabCollectionChangedCallbacks = []; + activeTabChangedCallbacks = []; + }); + + } + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbheader.directive.js index 15a1a09c05..4da7b90ad7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbheader.directive.js @@ -1,5 +1,14 @@ +/** +* @ngdoc directive +* @name umbraco.directives.directive:umbHeader +* @restrict E +* @function +* @deprecated since version 7.3 - use umbTabHeader instead +* @description +* The header on an editor that contains tabs using bootstrap tabs - THIS IS OBSOLETE, use umbTabHeader instead +**/ angular.module("umbraco.directives") -.directive('umbHeader', function($parse, $timeout){ +.directive('umbHeader', function ($parse, $timeout) { return { restrict: 'E', replace: true, diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtab.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtab.directive.js index 3758c64179..2e8bf7eba6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtab.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtab.directive.js @@ -4,11 +4,39 @@ * @restrict E **/ angular.module("umbraco.directives") -.directive('umbTab', function(){ - return { +.directive('umbTab', function ($parse) { + return { + require: "?^umbTabs", restrict: 'E', replace: true, - transclude: 'true', - templateUrl: 'views/directives/umb-tab.html' - }; + scope: { + id : "@", + tabId : "@rel" + }, + transclude: 'true', + templateUrl: 'views/directives/umb-tab.html', + link: function(scope, elem, attrs, tabsCtrl) { + + function toggleVisibility(tabId) { + if (scope.tabId === String(tabId)) { + elem.show(); + } + else { + elem.hide(); + } + } + + //need to make this optional for backwards compat since before we used to + // use bootstrap tabs and now we use our own faster implementation which + // gives us far more control but will still support the old way. + if (tabsCtrl != null) { + + tabsCtrl.onActiveTabChanged(function (tabId) { + toggleVisibility(tabId); + }); + + toggleVisibility(tabsCtrl.getActiveTab()); + } + } + }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtabheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtabheader.directive.js new file mode 100644 index 0000000000..3dac132d00 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbtabheader.directive.js @@ -0,0 +1,41 @@ +/** +* @ngdoc directive +* @name umbraco.directives.directive:umbTabHeader +* @restrict E +* @function +* @description +* The header on an editor that contains tabs +**/ +angular.module("umbraco.directives").directive('umbTabHeader', function($parse, $timeout) { + return { + require: "^umbTabs", + restrict: 'E', + replace: true, + transclude: 'true', + templateUrl: 'views/directives/umb-tab-header.html', + link: function(scope, iElement, iAttrs, tabsCtrl) { + + scope.showTabs = false; + scope.activeTabId = null; + scope.tabs = []; + + tabsCtrl.onTabCollectionChanged(function (tabs) { + scope.tabs = tabs; + scope.showTabs = scope.tabs.length > 0; + }); + + tabsCtrl.onActiveTabChanged(function (tabId) { + scope.activeTabId = tabId; + }); + + scope.changeTab = function(tabId) { + tabsCtrl.setActiveTab(tabId); + }; + + $timeout(function() { + //TODO: We'll need to destroy this I'm assuming! + $('.nav-pills, .nav-tabs').tabdrop(); + }, 500); + } + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/navresize.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/navresize.directive.js index 8f417effe5..7b21978f87 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/navresize.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/navresize.directive.js @@ -74,16 +74,19 @@ angular.module("umbraco.directives") } })); - $(window).bind("resize", function () { + var resizeCallback = function() { + _.debounce(function() { + //set the global app state + appState.setGlobalState("isTablet", ($(window).width() <= minScreenSize)); + setTreeMode(); + }, 100); + }; - //set the global app state - appState.setGlobalState("isTablet", ($(window).width() <= minScreenSize)); - - setTreeMode(); - }); + $(window).bind("resize", resizeCallback); //ensure to unregister from all events and kill jquery plugins scope.$on('$destroy', function () { + $(window).unbind("resize", resizeCallback); for (var e in evts) { eventsService.unsubscribe(evts[e]); } @@ -91,7 +94,6 @@ angular.module("umbraco.directives") navInnerContainer.resizable("destroy"); }); - //init //set the global app state appState.setGlobalState("isTablet", ($(window).width() <= minScreenSize)); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/detectfold.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/detectfold.directive.js index a0d1a8293b..6b548cdfe6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/util/detectfold.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/detectfold.directive.js @@ -12,7 +12,10 @@ angular.module("umbraco.directives.html") var state = false, parent = $(".umb-panel-body"), winHeight = $(window).height(), - calculate = _.throttle(function(){ + calculate = _.debounce(function () { + + console.log("calculating..."); + if(el && el.is(":visible") && !el.hasClass("umb-bottom-bar")){ //var parent = el.parent(); var hasOverflow = parent.innerHeight() < parent[0].scrollHeight; @@ -22,7 +25,7 @@ angular.module("umbraco.directives.html") } } return state; - }, 1000); + }, 500); scope.$watch(calculate, function(newVal, oldVal) { if(newVal !== oldVal){ @@ -34,12 +37,19 @@ angular.module("umbraco.directives.html") } }); - $(window).bind("resize", function () { - winHeight = $(window).height(); - el.removeClass("umb-bottom-bar"); - state = false; - calculate(); - }); + var resizeCallback = function() { + winHeight = $(window).height(); + el.removeClass("umb-bottom-bar"); + state = false; + calculate(); + }; + + $(window).bind("resize", resizeCallback); + + //ensure to unbind! + scope.$on('$destroy', function () { + $(window).unbind("resize", resizeCallback); + }); $('a[data-toggle="tab"]').on('shown', function (e) { calculate(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/content/edit.html index e29ee99925..5afa9d80a6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/edit.html @@ -4,8 +4,8 @@ ng-submit="save()" val-form-manager> - - + +
-
+ @@ -34,9 +34,8 @@ ng-repeat="property in tab.properties"> - - - + + + -