Changes how tabs work ... to no longer have to rely on bootstrap tabs and the hacky timing work-arounds, tabs are actually quite easy and now give us much more control.
Have made this change as backwards compatable (some things are deprecated though). Will update the other editors now.
This commit is contained in:
@@ -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: '<div class="umb-tab-buttons" detect-fold ng-class="{\'umb-dimmed\': busy}" ng-transclude></div>',
|
||||
link: function(scope, element, attrs, ngModel) {
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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 = [];
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
ng-submit="save()"
|
||||
val-form-manager>
|
||||
|
||||
<umb-panel ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-header tabs="content.tabs">
|
||||
<umb-panel umb-tabs="content.tabs" ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
|
||||
<umb-tab-header>
|
||||
|
||||
<div class="span7">
|
||||
<umb-content-name placeholder="@placeholders_entername"
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</umb-header>
|
||||
</umb-tab-header>
|
||||
|
||||
<umb-tab-view>
|
||||
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">
|
||||
@@ -34,9 +34,8 @@
|
||||
ng-repeat="property in tab.properties">
|
||||
<umb-editor model="property"></umb-editor>
|
||||
</umb-property>
|
||||
|
||||
|
||||
<div class="umb-tab-buttons" detect-fold ng-class="{'umb-dimmed': busy}">
|
||||
|
||||
<umb-editor-buttons>
|
||||
|
||||
<div class="btn-group" ng-show="listViewPath">
|
||||
<a class="btn" href="#{{listViewPath}}">
|
||||
@@ -72,12 +71,13 @@
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</umb-editor-buttons>
|
||||
|
||||
</div>
|
||||
</umb-tab>
|
||||
</umb-tab-view>
|
||||
|
||||
|
||||
<ul class="umb-panel-footer-nav nav nav-pills" ng-if="ancestors && ancestors.length > 0">
|
||||
<li ng-repeat="ancestor in ancestors">
|
||||
<a href="#/content/content/edit/{{ancestor.id}}">{{ancestor.name}}</a>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<div class="umb-panel-header">
|
||||
<div class="row-fluid">
|
||||
|
||||
<div ng-transclude></div>
|
||||
|
||||
<ul ng-show="showTabs" class="nav nav-tabs umb-nav-tabs span12">
|
||||
|
||||
<li ng-class="{active: activeTabId == tab.id, 'tab-error': tabHasError}" ng-repeat="tab in tabs" val-tab>
|
||||
<a href="#tab{{tab.id}}" ng-click="changeTab(tab.id)" prevent-default>{{ tab.label }}</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user