Angular, , . http://plnkr.co/edit/WnvZETQlxurhgcm1k6Hd?p=preview.
, , , , . :
$scope.tabs = [{
header: 'Tab A',
content: 'Content of Tab A'
},{
header: 'Tab B',
content: 'Content of Tab B'
}, {
header: 'Tab C',
content: 'Content of Tab C'
}];
HTML
HTML, ,
<tabs>
<tab-buttons>
<tab-button ng-repeat="tab in tabs">{{tab.header}}</tab-button>
</tab-buttons>
<tab-contents>
<tab-content ng-repeat="tab in tabs">{{tab.content}}</tab-body>
</tab-contents>
</tabs>
, , tabs. , require, , show , $index, ngRepeat .
app.directive('tabs', function($timeout) {
return {
restrict: 'E',
controller: function($element, $scope) {
var self = this;
this.show = function(index) {
var contents = $element.find('tab-content');
contents.removeClass('current');
angular.element(contents[index]).addClass('current');
var buttons = $element.find('tab-button');
buttons.removeClass('current');
angular.element(buttons[index]).addClass('current');
};
$timeout(function() {
self.show('0');
});
}
};
});
app.directive('tabButton', function() {
return {
restrict: 'E',
require: '^tabs',
link: function(scope, element, attr, tabs) {
element.on('click', function() {
tabs.show(scope.$index);
});
}
};
});
, CSS , .current, http://plnkr.co/edit/WnvZETQlxurhgcm1k6Hd?p=preview, .
HTML5 drag + drop API, + , , . , , - , . sortable , , sortable-item, .
<tabs sortable="tabs">
<tab-buttons>
<tab-button ng-repeat="tab in list" sortable-item="$index">{{tab.header}}</tab-button>
</tab-buttons>
<tab-contents>
<tab-content ng-repeat="tab in list">{{tab.content}}</tab-body>
</tab-contents>
</tabs>
sortable sortableItem ( http://www.html5rocks.com/en/tutorials/dnd/basics/)
app.directive('sortable', function() {
return {
controller: function($scope, $attrs) {
var listModel = null;
$scope.$watch($attrs.sortable, function(sortable) {
listModel = sortable;
});
this.move = function(fromIndex, toIndex) {
listModel.splice(toIndex, 0, listModel.splice(fromIndex, 1)[0]);
};
}
};
});
app.directive('sortableItem', function($window) {
return {
require: '^sortable',
link: function(scope, element, attrs, sortableController) {
var index = null;
scope.$watch(attrs.sortableItem, function(newIndex) {
index = newIndex;
});
attrs.$set('draggable', true);
var wrappedListeners = {
dragstart: function(e) {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.dropEffect = 'move';
e.dataTransfer.setData('application/json', index);
element.addClass('dragging');
},
dragend: function(e) {
e.stopPropagation();
element.removeClass('dragging');
},
dragenter: function(e) {
element.addClass('hover');
},
dragleave: function(e) {
element.removeClass('hover');
},
drop: function(e) {
e.preventDefault();
e.stopPropagation();
element.removeClass('hover');
var sourceIndex = e.dataTransfer.getData('application/json');
sortableController.move(sourceIndex, index);
}
};
var unwrappedListeners = {
dragover: function(e) {
e.preventDefault();
}
};
angular.forEach(wrappedListeners, function(listener, event) {
element.on(event, wrap(listener));
});
angular.forEach(unwrappedListeners, function(listener, event) {
element.on(event, listener);
});
function wrap(fn) {
return function(e) {
scope.$apply(function() {
fn(e);
});
};
}
}
};
});
, , sortableItem . , , sortable, . ngRepeat .
, , , . sortable , tabs, tabs .