reverts tabs back to use only bootstrap tabs (we can change that at a later date now that we have the code), have fixed up a lot of the detect-fold logic so that it doesn't run an insane amount of calculations, however now we need to properly fix the bootstrap tab event bindings.

This commit is contained in:
Shannon
2015-08-01 17:33:55 +02:00
parent 612484c0b6
commit d6b7bae38a
19 changed files with 72 additions and 263 deletions

View File

@@ -23,7 +23,6 @@ angular.module("umbraco.directives")
//I hate bootstrap tabs
//TODO: This is legacy since we aren't using bootstrap tabs anymore
$('a[data-toggle="tab"]').on('shown', update);
scope.$on('$destroy', function() {

View File

@@ -1,21 +0,0 @@
/**
* @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) {
}
};
});

View File

@@ -1,82 +0,0 @@
/**
* @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 ((angular.isArray(newValue) && angular.isArray(oldValue) && newValue.length !== oldValue.length|| (newValue !== undefined && oldValue === undefined))) {
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 = [];
});
}
};
});

View File

@@ -3,7 +3,6 @@
* @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
**/

View File

@@ -6,44 +6,9 @@
angular.module("umbraco.directives")
.directive('umbTab', function ($parse, $timeout) {
return {
require: "?^umbTabs",
restrict: 'E',
replace: true,
scope: {
id : "@",
tabId : "@rel"
},
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab.html',
link: function(scope, elem, attrs, tabsCtrl) {
function toggleVisibility(tabId) {
//default if there are no tabs
if (tabId === null) {
elem.addClass("active");
}
else {
if (scope.tabId === String(tabId)) {
elem.addClass("active");
}
else {
elem.removeClass("active");
}
}
}
//need to make this optional for backwards compat since before we used to
// use bootstrap tabs and now we use our own better implementation which
// gives us far more control but will still support the old way.
if (tabsCtrl) {
tabsCtrl.onActiveTabChanged(function (tabId) {
toggleVisibility(tabId);
});
toggleVisibility(tabsCtrl.getActiveTab());
}
}
templateUrl: 'views/directives/umb-tab.html'
};
});

View File

@@ -1,42 +0,0 @@
/**
* @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 = [];
if (tabsCtrl) {
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);
};
//TODO: We'll need to destroy this I'm assuming!
iElement.find('.nav-pills, .nav-tabs').tabdrop();
}
}
};
});

View File

@@ -5,31 +5,10 @@
**/
angular.module("umbraco.directives")
.directive('umbTabView', function($timeout, $log){
return {
require: "?^umbTabs",
return {
restrict: 'E',
replace: true,
transclude: 'true',
templateUrl: 'views/directives/umb-tab-view.html',
compile: function () {
return {
pre: function (scope, iElement, iAttrs, tabsCtrl) {
//if we have our custom tab directive it means we are not using bootstrap
// tabs, however if there isn't a directive we'll continue using bootsrap tabs
// this is done by adding 'tab-content' class for bootstrap or 'umb-tab-content'
// for our custom tabs.
//We also MUST do this on pre-linking because the tab-content class needs to be there
// before it hits the DOM so that bootstrap can do whatever it is that it does.
if (tabsCtrl) {
iElement.children("div:first").addClass("umb-tab-content");
}
else {
iElement.children("div:first").addClass("tab-content");
}
}
};
}
templateUrl: 'views/directives/umb-tab-view.html'
};
});

View File

@@ -7,15 +7,25 @@
angular.module("umbraco.directives.html")
.directive('detectFold', function ($timeout, $log, windowResizeListener) {
return {
require: "^?umbTabs",
restrict: 'A',
link: function (scope, el, attrs) {
var state = false;
var firstRun = false;
var parent = $(".umb-panel-body");
var winHeight = $(window).height();
var calculate = function() {
var calculate = function () {
console.log("calculating...");
if (el && el.is(":visible") && !el.hasClass("umb-bottom-bar")) {
//now that the element is visible, set the flag in a couple of seconds,
// this will ensure that loading time of a current tab get's completed and that
// we eventually stop watching to save on CPU time
$timeout(function() {
firstRun = true;
}, 4000);
//var parent = el.parent();
var hasOverflow = parent.innerHeight() < parent[0].scrollHeight;
//var belowFold = (el.offset().top + el.height()) > winHeight;
@@ -23,21 +33,42 @@ angular.module("umbraco.directives.html")
el.addClass("umb-bottom-bar");
}
}
return firstRun;
};
var resizeCallback = function(size) {
winHeight = size.height;
el.removeClass("umb-bottom-bar");
//state = false;
calculate();
};
windowResizeListener.register(resizeCallback);
//Only execute the watcher if this tab is the active (first) tab on load, otherwise there's no reason to execute
// the watcher since it will be recalculated when the tab changes!
if (el.closest(".umb-tab-pane").index() === 0) {
//run a watcher to ensure that the calculation occurs until it's firstRun but ensure
// the calculations are throttled to save a bit of CPU
var listener = scope.$watch(_.throttle(calculate, 1000), function (newVal, oldVal) {
if (newVal !== oldVal) {
//cancel the watch
console.log("WATCH CANCEL");
listener();
}
});
}
//Required for backwards compat for bootstrap tabs
$('a[data-toggle="tab"]').on('shown', calculate);
$('.nav-tabs a').on('shown', function (event) {
console.log("TAB SHOWN 1");
});
$('.nav-tabs a').on('shown.bs.tab', function (event) {
console.log("TAB SHOWN");
});
//ensure to unregister
scope.$on('$destroy', function() {
windowResizeListener.unregister(resizeCallback);

View File

@@ -36,11 +36,9 @@ function windowResizeListener($rootScope) {
}
},
unregister: function (fn) {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
if (registered[i] === fn) {
delete registered[i];
break;
}
var index = registered.indexOf(fn);
if (index > -1) {
registered.splice(index, 1);
}
}
};

View File

@@ -330,8 +330,7 @@
.tabbable {
.clearfix();
}
.tab-content,
.umb-tab-content {
.tab-content {
overflow: auto; // prevent content from running below tabs
}
@@ -344,13 +343,11 @@
// Show/hide tabbable areas
.tab-content > .tab-pane,
.pill-content > .pill-pane,
.umb-tab-content > .tab-pane {
.pill-content > .pill-pane {
display: none;
}
.tab-content > .active,
.pill-content > .active,
.umb-tab-content > .active {
.pill-content > .active {
display: block;
}

View File

@@ -1,10 +1,10 @@
<form ng-controller="Umbraco.DashboardController" class="umb-dashboard" val-form-manager>
<umb-panel umb-tabs="dashboard.tabs">
<umb-tab-header>
<umb-panel>
<umb-header tabs="dashboard.tabs">
<div class="umb-headline-editor-wrapper span12">
<h1>{{dashboard.name}}</h1>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in dashboard.tabs">
<div class="umb-pane">

View File

@@ -4,8 +4,8 @@
ng-submit="save()"
val-form-manager>
<umb-panel umb-tabs="content.tabs" ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
<umb-tab-header>
<umb-panel ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
<umb-header tabs="content.tabs">
<div class="span7">
<umb-content-name placeholder="@placeholders_entername"
@@ -20,12 +20,12 @@
<umb-options-menu ng-show="currentNode"
current-node="currentNode"
current-section="{{currentSection}}">
current-section="{{currentSection}}">
</umb-options-menu>
</div>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">
@@ -34,8 +34,9 @@
ng-repeat="property in tab.properties">
<umb-editor model="property"></umb-editor>
</umb-property>
<umb-editor-buttons>
<div class="umb-tab-buttons" detect-fold ng-class="{'umb-dimmed': busy}">
<div class="btn-group" ng-show="listViewPath">
<a class="btn" href="#{{listViewPath}}">
@@ -71,13 +72,12 @@
</ul>
</div>
</umb-editor-buttons>
</div>
</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>

View File

@@ -1,9 +1,9 @@
<umb-panel ng-controller="Umbraco.Editors.Content.RecycleBinController" umb-tabs>
<umb-tab-header>
<umb-panel ng-controller="Umbraco.Editors.Content.RecycleBinController">
<umb-header>
<div class="umb-headline-editor-wrapper span12">
<h1><localize key="general_recycleBin">Recycle Bin</localize></h1>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tabRecycleBin" rel="RecycleBin">
<umb-pane>

View File

@@ -5,7 +5,7 @@
val-form-manager>
<umb-panel>
<umb-tab-header>
<umb-header>
<div class="span7">
<umb-content-name
@@ -22,7 +22,7 @@
</umb-options-menu>
</div>
</div>
</umb-tab-header>
</umb-header>
<div class="umb-panel-body umb-scrollable row-fluid">
<div class="tab-content form-horizontal" style="padding-bottom: 90px">

View File

@@ -1,14 +0,0 @@
<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>

View File

@@ -1,5 +1,5 @@
<div class="umb-panel-body umb-scrollable row-fluid">
<div class="form-horizontal" ng-transclude>
<div class="tab-content form-horizontal" ng-transclude>
</div>
</div>

View File

@@ -3,8 +3,8 @@
ng-show="loaded"
ng-submit="save()"
val-form-manager>
<umb-panel umb-tabs="content.tabs" ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
<umb-tab-header>
<umb-panel ng-class="{'editor-breadcrumb': ancestors && ancestors.length > 0}">
<umb-header tabs="content.tabs">
<div class="span7">
<umb-content-name placeholder="@placeholders_entername"
@@ -23,7 +23,7 @@
</umb-options-menu>
</div>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">

View File

@@ -1,9 +1,9 @@
<umb-panel ng-controller="Umbraco.Editors.Media.RecycleBinController" umb-tabs>
<umb-tab-header>
<umb-panel ng-controller="Umbraco.Editors.Media.RecycleBinController">
<umb-header>
<div class="umb-headline-editor-wrapper span12">
<h1><localize key="general_recycleBin">Recycle Bin</localize></h1>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tabRecycleBin" rel="RecycleBin">
<umb-pane>

View File

@@ -3,8 +3,8 @@
ng-show="loaded"
ng-submit="save()"
val-form-manager>
<umb-panel umb-tabs="content.tabs">
<umb-tab-header>
<umb-panel>
<umb-header tabs="content.tabs">
<div class="span7" ng-if="content.membershipScenario == 0">
<umb-content-name
@@ -28,7 +28,7 @@
</div>
</div>
</umb-tab-header>
</umb-header>
<umb-tab-view>
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">