842 lines
21 KiB
JavaScript
842 lines
21 KiB
JavaScript
/*
|
|
* Axelor Business Solutions
|
|
*
|
|
* Copyright (C) 2005-2019 Axelor (<http://axelor.com>).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
(function() {
|
|
|
|
"use strict";
|
|
|
|
var ui = angular.module('axelor.ui');
|
|
|
|
// this directive is used as a replacement for ng-transclude directive
|
|
// which fails to keep scope hierarchy (see: https://github.com/angular/angular.js/issues/1809)
|
|
ui.directive('uiTransclude', function() {
|
|
return {
|
|
compile: function(tElement, tAttrs, transclude) {
|
|
return function(scope, element, attrs, ctrl) {
|
|
transclude(scope.$new(), function(clone) {
|
|
element.append(clone);
|
|
});
|
|
};
|
|
}
|
|
};
|
|
});
|
|
|
|
/**
|
|
* The Group widget.
|
|
*
|
|
*/
|
|
ui.formWidget('Group', {
|
|
|
|
css: 'form-item-group',
|
|
cellCss: 'form-item v-align-top',
|
|
|
|
link: function(scope, element, attrs) {
|
|
|
|
var props = scope.field;
|
|
|
|
scope.collapsed = false;
|
|
|
|
scope.canCollapse = function() {
|
|
return props.canCollapse || props.collapseIf;
|
|
};
|
|
|
|
scope.setCollapsed = function(collapsed) {
|
|
scope.collapsed = collapsed;
|
|
element.children('legend').nextAll(':not(br)')[collapsed ? 'hide' : 'show']();
|
|
axelor.$adjustSize();
|
|
};
|
|
|
|
scope.toggle = function() {
|
|
scope.collapsed = !scope.collapsed;
|
|
scope.setCollapsed(scope.collapsed);
|
|
};
|
|
|
|
scope.$watch("attr('collapse')", function groupCollapseWatch(collapsed) {
|
|
scope.setCollapsed(collapsed);
|
|
});
|
|
|
|
// if auto title, then don't show it
|
|
if (attrs.title === attrs.field) {
|
|
attrs.$set('title', '');
|
|
}
|
|
|
|
if (props.showTitle !== false) {
|
|
scope.$watch('attr("title")', function groupTitleWatch(value){
|
|
scope.title = value;
|
|
});
|
|
}
|
|
},
|
|
transclude: true,
|
|
template:
|
|
'<fieldset ng-class="{\'bordered-box\': title, \'has-title\': title}" x-layout-selector="> div:first">'+
|
|
'<legend ng-show="title">'+
|
|
'<i ng-show="canCollapse()" ng-click="toggle()" ng-class="{\'fa fa-plus\': collapsed, \'fa fa-minus\': !collapsed}"></i>'+
|
|
'<span ng-bind-html="title"></span></legend>'+
|
|
'<div ui-transclude></div>'+
|
|
'</fieldset>'
|
|
});
|
|
|
|
ui.formWidget('Portlet', {
|
|
|
|
css: 'form-item-portlet',
|
|
cellCss: 'form-item v-align-top',
|
|
|
|
showTitle: false,
|
|
|
|
link: function(scope, element, attrs) {
|
|
|
|
var field = scope.field;
|
|
|
|
scope.canSearch = field.canSearch !== "false";
|
|
scope.actionName = field.action;
|
|
|
|
if (field.name) {
|
|
scope.formPath = field.name;
|
|
}
|
|
|
|
if (field.height) {
|
|
element.height(field.height);
|
|
}
|
|
|
|
element.resizable({
|
|
handles: 's',
|
|
resize: _.debounce(function() {
|
|
axelor.$adjustSize();
|
|
element.width('auto');
|
|
}, 100)
|
|
});
|
|
},
|
|
|
|
template:
|
|
'<div>'+
|
|
'<div ui-view-portlet x-action="{{actionName}}" x-can-search="{{canSearch}}"></div>'+
|
|
'</div>'
|
|
});
|
|
|
|
ui.formWidget('Dashlet', {
|
|
|
|
css: 'dashboard',
|
|
|
|
showTitle: false,
|
|
|
|
link: function(scope, element, attrs) {
|
|
|
|
var field = scope.field;
|
|
var dashlet = _.extend({}, scope.field);
|
|
|
|
scope.dashlet = dashlet;
|
|
scope.formPath = field.name || field.action;
|
|
|
|
scope.$watch('attr("title")', function dashletTitleWatch(title, old) {
|
|
if (title === old) {
|
|
return;
|
|
}
|
|
var dashletScope = element.children('[ui-view-dashlet]').scope();
|
|
if (dashletScope) {
|
|
dashletScope.title = title;
|
|
}
|
|
});
|
|
},
|
|
|
|
template:
|
|
'<div>'+
|
|
'<div ui-view-dashlet></div>'+
|
|
'</div>'
|
|
});
|
|
|
|
/**
|
|
* The Tabs widget (notebook).
|
|
*/
|
|
ui.formWidget('Tabs', {
|
|
|
|
cellCss: 'form-item v-align-top',
|
|
|
|
widgets: ['Notebook'],
|
|
|
|
controller: ['$scope', '$element', function($scope, $element) {
|
|
|
|
var tabs = $scope.tabs = [],
|
|
selected = -1;
|
|
|
|
var doOnSelectPending = false;
|
|
var doOnSelect = _.debounce(function () {
|
|
var select = tabs[selected];
|
|
if (doOnSelectPending || !select) {
|
|
return;
|
|
}
|
|
doOnSelectPending = true;
|
|
$scope.waitForActions(function () {
|
|
if (select.handleSelect) {
|
|
select.handleSelect();
|
|
}
|
|
$scope.waitForActions(function () {
|
|
doOnSelectPending = false;
|
|
});
|
|
});
|
|
}, 100);
|
|
|
|
$scope.select = function(tab) {
|
|
|
|
var current = selected;
|
|
|
|
angular.forEach(tabs, function(tab, i){
|
|
tab.tabSelected = false;
|
|
});
|
|
|
|
tab.tabSelected = true;
|
|
selected = _.indexOf(tabs, tab);
|
|
|
|
if (current === selected) {
|
|
return;
|
|
}
|
|
|
|
setTimeout(function() {
|
|
if ($scope.$tabs) {
|
|
$scope.$tabs.trigger('adjust:tabs');
|
|
}
|
|
axelor.$adjustSize();
|
|
if(current != selected){
|
|
doOnSelect();
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.$on('on:edit', function (e, record) {
|
|
if ($scope.record === record) {
|
|
doOnSelect();
|
|
}
|
|
});
|
|
|
|
this.addTab = function(tab) {
|
|
if (tabs.length === 0) $scope.select(tab);
|
|
tab.index = tabs.length;
|
|
tabs.push(tab);
|
|
};
|
|
|
|
function inRange(index) {
|
|
return index > -1 && index < tabs.length;
|
|
}
|
|
|
|
function findItem(index) {
|
|
return $element.find('ul.nav-tabs:first > li:nth-child(' + (index+1) + ')');
|
|
}
|
|
|
|
this.showTab = function(index) {
|
|
|
|
if (!inRange(index)) {
|
|
return;
|
|
}
|
|
|
|
var tab = tabs[index];
|
|
var item = findItem(index);
|
|
|
|
tab.hidden = false;
|
|
item.show();
|
|
|
|
if (selected == -1 || selected === index) {
|
|
return $scope.select(tabs[index]);
|
|
}
|
|
|
|
axelor.$adjustSize();
|
|
};
|
|
|
|
this.hideTab = function(index) {
|
|
|
|
if (!inRange(index))
|
|
return;
|
|
|
|
var item = findItem(index),
|
|
tab = tabs[index];
|
|
|
|
var wasHidden = item.is(":hidden");
|
|
|
|
item.hide();
|
|
item.removeClass('active');
|
|
|
|
tab.hidden = true;
|
|
tab.tabSelected = false;
|
|
|
|
if (!wasHidden && selected > -1 && selected !== index)
|
|
return axelor.$adjustSize();
|
|
|
|
for(var i = 0 ; i < tabs.length ; i++) {
|
|
tab = tabs[i];
|
|
if (!tab.hidden) {
|
|
return $scope.select(tabs[i]);
|
|
}
|
|
}
|
|
selected = -1;
|
|
};
|
|
|
|
$scope.setTitle = function(value,index){
|
|
var item = findItem(index),
|
|
pageScope = item.first().data('$scope');
|
|
|
|
pageScope.tab.title = value;
|
|
};
|
|
}],
|
|
|
|
link: function(scope, elem, attrs) {
|
|
|
|
var props = scope.field;
|
|
|
|
scope.$tabs = $(elem).bsTabs({
|
|
closable: false
|
|
});
|
|
|
|
elem.on('click', '.dropdown-toggle', function(e){
|
|
axelor.$adjustSize();
|
|
});
|
|
|
|
// set height (#1011)
|
|
if (props.height) {
|
|
elem.children('.tab-content:first').height(props.height);
|
|
}
|
|
},
|
|
transclude: true,
|
|
template:
|
|
'<div class="tabbable-tabs">' +
|
|
'<div class="nav-tabs-wrap">' +
|
|
'<div class="nav-tabs-scroll-l"><a tabindex="-1" href="#"><i class="fa fa-chevron-left"></i></a></div>' +
|
|
'<div class="nav-tabs-scroll-r"><a tabindex="-1" href="#"><i class="fa fa-chevron-right"></i></a></div>' +
|
|
'<div class="nav-tabs-strip">' +
|
|
'<ul class="nav nav-tabs">' +
|
|
'<li tabindex="-1" ng-repeat="tab in tabs" ng-class="{active:tab.tabSelected}">'+
|
|
'<a tabindex="-1" href="" ng-click="select(tab)">'+
|
|
'<img class="prefix-icon" ng-show="tab.icon" ng-src="{{tab.icon}}">'+
|
|
'<span ng-bind-html="tab.title"></span>'+
|
|
'</a>' +
|
|
'</li>' +
|
|
'</ul>' +
|
|
'</div>' +
|
|
'<div class="nav-tabs-menu">'+
|
|
'<div class="dropdown pull-right">'+
|
|
'<a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="caret"></i></a>'+
|
|
'<ul class="dropdown-menu" role="menu">'+
|
|
'<li ng-repeat="tab in tabs">'+
|
|
'<a tabindex="-1" href="javascript: void(0)" ng-click="select(tab)" ng-bind-html="tab.title"></a>'+
|
|
'</li>' +
|
|
'</ul>' +
|
|
'</a>'+
|
|
'</div>'+
|
|
'</div>'+
|
|
'</div>' +
|
|
'<div class="tab-content" ui-transclude></div>' +
|
|
'</div>'
|
|
});
|
|
|
|
/**
|
|
* The Tab widget (notebook page).
|
|
*/
|
|
ui.formWidget('Tab', {
|
|
|
|
require: '^uiTabs',
|
|
|
|
widgets: ['Page'],
|
|
|
|
handles: ['isHidden'],
|
|
|
|
link: function(scope, elem, attrs, tabs) {
|
|
|
|
scope.tabSelected = false;
|
|
scope.icon = scope.field && scope.field.icon;
|
|
|
|
tabs.addTab(scope);
|
|
|
|
scope.$watch('attr("title")', function tabTitleWatch(value){
|
|
scope.title = value;
|
|
});
|
|
|
|
scope.$watch("isHidden()", function tabHiddenWatch(hidden, old) {
|
|
if (hidden) {
|
|
return tabs.hideTab(scope.index);
|
|
}
|
|
return tabs.showTab(scope.index);
|
|
});
|
|
|
|
scope.handleSelect = function () {
|
|
var onSelect = scope.$events.onSelect;
|
|
if (onSelect && !elem.is(":hidden")) {
|
|
onSelect();
|
|
}
|
|
};
|
|
},
|
|
cellCss: 'form-item v-align-top',
|
|
transclude: true,
|
|
template: '<div ui-actions class="tab-pane" ng-class="{active: tabSelected}" x-layout-selector="> div:first">'+
|
|
'<div ui-transclude></div>'+
|
|
'</div>'
|
|
});
|
|
|
|
ui.formWidget('ButtonGroup', {
|
|
|
|
link: function (scope, element, attrs) {
|
|
function adjustButtons() {
|
|
var visible = element.children('.btn:visible').length;
|
|
if (visible) {
|
|
element.children('.btn:visible')
|
|
.css('max-width', (100.00/visible) + '%')
|
|
.css('width', (100.00/visible) + '%');
|
|
}
|
|
}
|
|
scope.$watch(adjustButtons);
|
|
scope.$callWhen(function () {
|
|
return element.is(':visible');
|
|
}, adjustButtons);
|
|
},
|
|
transclude: true,
|
|
template_editable: null,
|
|
template_readonly: null,
|
|
template:
|
|
"<div class='btn-group' ui-transclude></div>"
|
|
});
|
|
|
|
ui.formWidget('Panel', {
|
|
|
|
showTitle: false,
|
|
|
|
link: function (scope, element, attrs) {
|
|
|
|
var field = scope.field || {};
|
|
var body = element.children(".panel-body");
|
|
|
|
element.addClass(field.serverType);
|
|
if (field.sidebar && !attrs.itemSpan) {
|
|
attrs.$set('itemSpan', 12, true, 'x-item-span');
|
|
}
|
|
|
|
scope.menus = null;
|
|
if (field.menu) {
|
|
scope.menus = [field.menu];
|
|
}
|
|
|
|
scope.canCollapse = function() {
|
|
return field.canCollapse || field.collapseIf;
|
|
};
|
|
|
|
scope.setCollapsed = function(collapsed) {
|
|
var old = scope.collapsed;
|
|
var action = collapsed ? "hide" : "show";
|
|
|
|
scope.collapsed = collapsed;
|
|
scope.collapsedIcon = collapsed ? 'fa-chevron-down' : 'fa-chevron-up';
|
|
|
|
if (collapsed === old) {
|
|
return;
|
|
}
|
|
|
|
element.removeClass("collapsed");
|
|
body[action]("blind", 200, function () {
|
|
element.toggleClass("collapsed", !!collapsed);
|
|
if (body.css('display') !== 'none' && action === 'hide') {
|
|
body.hide();
|
|
}
|
|
axelor.$adjustSize();
|
|
});
|
|
};
|
|
|
|
scope.toggle = function() {
|
|
if (scope.canCollapse()) {
|
|
scope.setCollapsed(!scope.collapsed);
|
|
}
|
|
};
|
|
|
|
scope.$watch("attr('collapse')", function panelCollapseWatch(collapsed) {
|
|
scope.setCollapsed(collapsed);
|
|
});
|
|
|
|
var nested = element.parents('.panel:first').length > 0;
|
|
if (nested) {
|
|
element.addClass("panel-nested");
|
|
}
|
|
if (field.showFrame === false) {
|
|
element.addClass('noframe');
|
|
}
|
|
scope.notitle = field.showFrame === false || field.showTitle === false;
|
|
scope.title = field.title;
|
|
scope.$watch('attr("title")', function panelTitleWatch(title, old) {
|
|
if (title === undefined || title === old) return;
|
|
scope.title = title;
|
|
});
|
|
|
|
var icon = field.icon;
|
|
var iconBg = field.iconBackground;
|
|
|
|
if (icon && icon.indexOf('fa-') === 0) {
|
|
scope.icon = icon;
|
|
} else if (icon) {
|
|
scope.image = icon;
|
|
}
|
|
|
|
if (scope.icon && iconBg) {
|
|
setTimeout(function() {
|
|
var iconElem = element.children('.panel-header').children('.panel-icon');
|
|
if (iconBg.indexOf("#") === 0) {
|
|
iconElem.css('background-color', iconBg);
|
|
} else {
|
|
iconElem.addClass('bg-' + iconBg);
|
|
}
|
|
iconElem.addClass('has-bg');
|
|
iconElem.find('i').addClass('fg-white');
|
|
});
|
|
}
|
|
|
|
setTimeout(function () {
|
|
var nestedJson = element.parents('.panel-json:first').length > 0;
|
|
if (nestedJson) {
|
|
element.removeClass("panel-nested");
|
|
}
|
|
});
|
|
},
|
|
|
|
transclude: true,
|
|
template:
|
|
"<div class='panel panel-default'>" +
|
|
"<div class='panel-header' ng-click='toggle()' ng-if='!notitle && field.title' ng-class=\"{'clickable-header' : canCollapse()}\" tabindex='-1'>" +
|
|
"<div class='panel-icon' ng-if='icon'><i class='fa' ng-class='icon'></i></div>" +
|
|
"<img class='panel-image' ng-if='image' ng-src='{{image}}'>" +
|
|
"<div class='panel-title'>{{title}}</div>" +
|
|
"<div ng-if='menus' ui-menu-bar menus='menus' handler='this'></div>" +
|
|
"<div ng-show='canCollapse()' class='panel-icons'>" +
|
|
"<a href=''><i class='fa' ng-class='collapsedIcon'></i></a>" +
|
|
"</div>" +
|
|
"</div>" +
|
|
"<div class='panel-body' ui-transclude></div>" +
|
|
"</div>"
|
|
});
|
|
|
|
ui.formWidget('PanelStack', {
|
|
transclude: true,
|
|
template: "<div class='panel-stack'>" +
|
|
"<span ui-transclude></span>" +
|
|
"</div>"
|
|
});
|
|
|
|
ui.formWidget('PanelTabs', {
|
|
|
|
link: function (scope, element, attrs) {
|
|
|
|
scope.tabs = [];
|
|
scope.more = null;
|
|
|
|
element.find('> .tab-content > div').each(function (index) {
|
|
var elem = $(this);
|
|
var tab = {
|
|
title: elem.attr('x-title'),
|
|
selected: false,
|
|
hidden: false,
|
|
elem: elem,
|
|
tabItem: $(),
|
|
menuItem: $()
|
|
};
|
|
scope.tabs.push(tab);
|
|
});
|
|
|
|
var selected = null;
|
|
var adjustPending = false;
|
|
|
|
function findTab(tab) {
|
|
var found = scope.tabs[tab] || tab;
|
|
if (!found || _.isNumber(found)) {
|
|
return null;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
var doOnSelectPending = false;
|
|
var doOnSelect = _.debounce(function () {
|
|
if (doOnSelectPending || !selected || !selected.elem) {
|
|
return;
|
|
}
|
|
doOnSelectPending = true;
|
|
scope.waitForActions(function () {
|
|
var elemScope = selected.elem.scope();
|
|
if (elemScope.handleSelect) {
|
|
elemScope.handleSelect();
|
|
}
|
|
doOnSelectPending = false;
|
|
});
|
|
}, 100);
|
|
|
|
scope.selectTab = function(tab) {
|
|
var current = selected;
|
|
var found = findTab(tab);
|
|
if (!found) {
|
|
return;
|
|
}
|
|
scope.tabs.forEach(function (current) {
|
|
current.selected = false;
|
|
current.elem.hide();
|
|
});
|
|
|
|
selected = found;
|
|
|
|
found.selected = true;
|
|
found.elem.show();
|
|
|
|
found.elem
|
|
.add(found.tabItem)
|
|
.add(found.menuItem)
|
|
.addClass('active');
|
|
|
|
setTimeout(function () {
|
|
scope.$broadcast('tab:select');
|
|
elemTabs.removeClass('open');
|
|
elemMenu.removeClass('open');
|
|
axelor.$adjustSize();
|
|
if (current != selected) {
|
|
doOnSelect();
|
|
}
|
|
});
|
|
};
|
|
|
|
scope.showTab = function (tab) {
|
|
var found = findTab(tab);
|
|
if (!found) {
|
|
return;
|
|
}
|
|
|
|
adjustPending = true;
|
|
|
|
found.hidden = false;
|
|
found.tabItem.show();
|
|
|
|
if (!selected || selected === found) {
|
|
return scope.selectTab(found);
|
|
}
|
|
|
|
found.elem.hide();
|
|
|
|
axelor.$adjustSize();
|
|
};
|
|
|
|
scope.hideTab = function (tab) {
|
|
var found = findTab(tab);
|
|
if (!found) {
|
|
return;
|
|
}
|
|
|
|
adjustPending = true;
|
|
|
|
var wasHidden = found.hidden;
|
|
|
|
found.hidden = true;
|
|
found.selected = false;
|
|
found.elem.hide();
|
|
|
|
found.tabItem.add(found.menuItem).hide().removeClass('active');
|
|
|
|
if (!wasHidden && selected && selected !== found) {
|
|
return axelor.$adjustSize();
|
|
}
|
|
|
|
var tabs = scope.tabs;
|
|
for(var i = 0 ; i < tabs.length ; i++) {
|
|
tab = tabs[i];
|
|
if (!tab.hidden) {
|
|
return scope.selectTab(tabs[i]);
|
|
}
|
|
}
|
|
selected = null;
|
|
};
|
|
|
|
var lastWidth = 0;
|
|
var lastTab = null;
|
|
|
|
var elemTabs = $();
|
|
var elemMenu = $();
|
|
var elemMenuTitle = $();
|
|
var elemMenuItems = $();
|
|
|
|
function setup() {
|
|
elemTabs = element.children('.nav-tabs').children('li:not(.dropdown)');
|
|
elemMenu = element.children('.nav-tabs').children('li.dropdown');
|
|
elemMenuTitle = elemMenu.children('a:first').children('span');
|
|
elemMenuItems = elemMenu.find('li');
|
|
|
|
_.each(scope.tabs, function (tab, index) {
|
|
tab.tabItem = $(elemTabs[index]);
|
|
tab.menuItem = $(elemMenuItems[index]);
|
|
});
|
|
}
|
|
|
|
var setMenuTitle = (function() {
|
|
var setActive = _.debounce(function(selected) {
|
|
elemMenu.toggleClass('active', !!selected);
|
|
});
|
|
return function setMenuTitle(selected) {
|
|
elemMenu.show();
|
|
elemMenuTitle.html(selected && selected.title);
|
|
setActive(selected);
|
|
};
|
|
}());
|
|
|
|
function adjust() {
|
|
if (elemTabs === null || !scope.tabs || element.is(":hidden")) {
|
|
return;
|
|
}
|
|
|
|
var parentWidth = element.width() - 2;
|
|
if (parentWidth === lastWidth && lastTab === selected && !adjustPending) {
|
|
return;
|
|
}
|
|
lastWidth = parentWidth;
|
|
lastTab = selected;
|
|
|
|
elemTabs.parent().css('visibility', 'hidden');
|
|
elemMenu.hide();
|
|
|
|
// show visible tabs
|
|
scope.tabs.forEach(function (tab, i) {
|
|
if (tab.hidden) {
|
|
$(elemTabs[i]).hide();
|
|
} else {
|
|
$(elemTabs[i]).show();
|
|
}
|
|
});
|
|
|
|
if (elemTabs.parent().width() <= parentWidth) {
|
|
elemTabs.parent().css('visibility', '');
|
|
return;
|
|
}
|
|
|
|
setMenuTitle(null);
|
|
|
|
var elem = null;
|
|
var index = elemTabs.length;
|
|
var selectedIndex = scope.tabs.indexOf(selected);
|
|
|
|
while (elemTabs.parent().width() > parentWidth) {
|
|
elem = $(elemTabs[--index]);
|
|
elem.hide();
|
|
if (index === selectedIndex) {
|
|
setMenuTitle(selected);
|
|
}
|
|
}
|
|
|
|
elemMenuItems.hide();
|
|
var tab = null;
|
|
while(index < scope.tabs.length) {
|
|
tab = scope.tabs[index++];
|
|
if (!tab.hidden) {
|
|
tab.menuItem.show();
|
|
}
|
|
}
|
|
|
|
elemTabs.parent().css('visibility', '');
|
|
}
|
|
|
|
var adjusting = false;
|
|
scope.$onAdjust(function() {
|
|
if (adjusting) { return; }
|
|
try {
|
|
adjusting = true;
|
|
adjust();
|
|
} finally {
|
|
adjusting = false;
|
|
adjustPending = false;
|
|
}
|
|
}, 10);
|
|
|
|
scope.$timeout(function() {
|
|
setup();
|
|
var first = _.find(scope.tabs, function (tab) {
|
|
return !tab.hidden;
|
|
});
|
|
if (first) {
|
|
scope.selectTab(first);
|
|
}
|
|
});
|
|
|
|
scope.$on('on:edit', function (e, record) {
|
|
if (scope.record === record && !doOnSelectPending) {
|
|
scope.ajaxStop(doOnSelect, 100);
|
|
}
|
|
});
|
|
|
|
scope.$watch(function tabsWatch() {
|
|
var hidden = scope.attr('hidden');
|
|
if (hidden) return;
|
|
// show selected tab only
|
|
scope.tabs.forEach(function (tab) {
|
|
if (!tab.selected) tab.elem.hide();
|
|
});
|
|
});
|
|
},
|
|
|
|
transclude: true,
|
|
template:
|
|
"<div class='panel-tabs tabbable-tabs'>" +
|
|
"<ul class='nav nav-tabs nav-tabs-responsive'>" +
|
|
"<li ng-repeat='tab in tabs' ng-class='{active: tab.selected}'>" +
|
|
"<a tabindex='-1' href='' ng-click='selectTab(tab)' ng-bind-html='tab.title'></a>" +
|
|
"</li>" +
|
|
"<li class='dropdown' style='display: none'>" +
|
|
"<a tabindex='-1' href='' class='dropdown-toggle' data-toggle='dropdown'><span></span><b class='caret'></b></a>" +
|
|
"<ul class='dropdown-menu pull-right'>" +
|
|
"<li ng-repeat='tab in tabs' ng-class='{active: tab.selected}'>" +
|
|
"<a tabindex='-1' href='' ng-click='selectTab(tab)' ng-bind-html='tab.title'></a>" +
|
|
"</li>" +
|
|
"</ul>" +
|
|
"</li>" +
|
|
"</ul>" +
|
|
"<div class='tab-content' ui-transclude></div>" +
|
|
"</div>"
|
|
});
|
|
|
|
ui.formWidget('PanelTab', {
|
|
|
|
link: function (scope, element, attrs) {
|
|
|
|
var index = element.parent().children().index(element);
|
|
var tab = null;
|
|
var isHidden = scope.isHidden;
|
|
|
|
function findTab() {
|
|
return tab || (tab = (scope.tabs||[])[index]) || {};
|
|
}
|
|
|
|
scope.handleSelect = function () {
|
|
var onTabSelect = scope.$events.onTabSelect;
|
|
if (onTabSelect && !element.is(":hidden")) {
|
|
onTabSelect();
|
|
}
|
|
};
|
|
|
|
scope.isHidden = function () {
|
|
var tab = findTab();
|
|
return !tab.selected || isHidden.call(scope);
|
|
};
|
|
|
|
scope.$watch("attr('title')", function tabTitleWatch(value) {
|
|
var tab = findTab();
|
|
tab.title = value;
|
|
});
|
|
|
|
scope.$watch("attr('hidden')", function tabHiddenWatch(hidden, old) {
|
|
scope.$evalAsync(function () {
|
|
if (hidden) {
|
|
return scope.hideTab(index);
|
|
}
|
|
return scope.showTab(index);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
})();
|