Added the property grouping support to the Inspector
This commit is contained in:
parent
43dde06559
commit
478ddabeca
|
|
@ -11406,6 +11406,29 @@ html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-contain
|
|||
-moz-border-radius: 0 0 2px 0;
|
||||
border-radius: 0 0 2px 0;
|
||||
}
|
||||
.inspector-fields tr.group {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.inspector-fields tr.group th {
|
||||
background: #e0e4e5;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.inspector-fields tr.collapsed {
|
||||
display: none;
|
||||
}
|
||||
.inspector-fields tr.expanded {
|
||||
display: table-row;
|
||||
}
|
||||
.inspector-fields.has-groups th {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.inspector-fields.has-groups tr.grouped th {
|
||||
padding-left: 35px;
|
||||
}
|
||||
.inspector-fields td {
|
||||
font-weight: 300;
|
||||
border-left: 1px solid #f2f2f2;
|
||||
|
|
@ -11447,16 +11470,18 @@ html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-contain
|
|||
}
|
||||
.inspector-fields th > div {
|
||||
position: relative;
|
||||
}
|
||||
.inspector-fields th > div > div {
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.inspector-fields th > div span.info {
|
||||
.inspector-fields th > div > div span.info {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: -6px;
|
||||
right: -1px;
|
||||
top: 3px;
|
||||
font-size: 14px;
|
||||
width: 10px;
|
||||
|
|
@ -11465,10 +11490,57 @@ html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-contain
|
|||
opacity: 0.4;
|
||||
filter: alpha(opacity=40);
|
||||
}
|
||||
.inspector-fields th > div span.info:hover {
|
||||
.inspector-fields th > div > div span.info:before {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.inspector-fields th > div > div span.info:hover {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.inspector-fields th > div a.expandControl {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
left: -15px;
|
||||
top: 2px;
|
||||
text-indent: -100000em;
|
||||
}
|
||||
.inspector-fields th > div a.expandControl span {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
.inspector-fields th > div a.expandControl span:after {
|
||||
font-family: FontAwesome;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-decoration: inherit;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
*margin-right: .3em;
|
||||
content: "\f105";
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: -2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
font-size: 13px;
|
||||
color: #333333;
|
||||
text-indent: 0;
|
||||
}
|
||||
.inspector-fields th > div a.expandControl.expanded span:after {
|
||||
font-family: FontAwesome;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-decoration: inherit;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
*margin-right: .3em;
|
||||
content: "\f107";
|
||||
left: 2px;
|
||||
}
|
||||
.inspector-fields input[type=text] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
|
@ -11560,9 +11632,9 @@ div.control-popover.control-inspector > div:after {
|
|||
top: 5px;
|
||||
color: #95a5a6;
|
||||
}
|
||||
.select2-drop.ocInspectorDropdown .select2-search .select2-input {
|
||||
.select2-drop.ocInspectorDropdown .select2-search input.select2-input {
|
||||
min-height: 26px;
|
||||
background: transparent;
|
||||
background: transparent!important;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
* Each element in the array is an object with the following properties:
|
||||
* - property
|
||||
* - title
|
||||
* - group (optional)
|
||||
* - type (currently supported types are: string, checkbox, dropdown)
|
||||
* - description (optional)
|
||||
* - validationPattern (regex pattern for for validating the value, supported by the text editor)
|
||||
|
|
@ -84,42 +85,47 @@
|
|||
'an hidden input element with the data-inspector-values property.')
|
||||
}
|
||||
|
||||
Inspector.prototype.getPopoverTemplate = function() {
|
||||
return ' \
|
||||
<div class="popover-head"> \
|
||||
<h3>{{title}}</h3> \
|
||||
{{#description}} \
|
||||
<p>{{description}}</p> \
|
||||
{{/description}} \
|
||||
<button type="button" class="close" \
|
||||
data-dismiss="popover" \
|
||||
aria-hidden="true">×</button> \
|
||||
</div> \
|
||||
<form> \
|
||||
<table class="inspector-fields"> \
|
||||
{{#properties}} \
|
||||
<tr id="{{#propFormat}}{{property}}{{/propFormat}}"> \
|
||||
<th><div title="{{title}}"> \
|
||||
{{title}} \
|
||||
{{#info}}{{/info}} \
|
||||
</div></th> \
|
||||
{{#editor}}{{/editor}} \
|
||||
</tr> \
|
||||
{{/properties}} \
|
||||
</table> \
|
||||
<form> \
|
||||
Inspector.prototype.getPopoverTemplate = function() {
|
||||
return ' \
|
||||
<div class="popover-head"> \
|
||||
<h3>{{title}}</h3> \
|
||||
{{#description}} \
|
||||
<p>{{description}}</p> \
|
||||
{{/description}} \
|
||||
<button type="button" class="close" \
|
||||
data-dismiss="popover" \
|
||||
aria-hidden="true">×</button> \
|
||||
</div> \
|
||||
<form> \
|
||||
<table class="inspector-fields {{#tableClass}}{{/tableClass}}"> \
|
||||
{{#properties}} \
|
||||
<tr id="{{#propFormat}}{{property}}{{/propFormat}}" \
|
||||
{{#dataGroupIndex}}{{/dataGroupIndex}} \
|
||||
class="{{#cellClass}}{{/cellClass}}"> \
|
||||
<th {{#colspan}}{{/colspan}}><div><div class="title-element" title="{{title}}"> \
|
||||
{{#expandControl}}{{/expandControl}} \
|
||||
{{title}} \
|
||||
{{#info}}{{/info}} \
|
||||
</div></div></th> \
|
||||
{{#editor}}{{/editor}} \
|
||||
</tr> \
|
||||
{{/properties}} \
|
||||
</table> \
|
||||
<form> \
|
||||
'
|
||||
}
|
||||
|
||||
Inspector.prototype.init = function() {
|
||||
var self = this,
|
||||
fieldsConfig = this.preprocessConfig(),
|
||||
data = {
|
||||
title: this.$el.data('inspector-title'),
|
||||
description: this.$el.data('inspector-description'),
|
||||
properties: this.config,
|
||||
properties: fieldsConfig.properties,
|
||||
editor: function() {
|
||||
return function(text, render) {
|
||||
return self.renderEditor(this, render)
|
||||
if (this.itemType == 'property')
|
||||
return self.renderEditor(this, render)
|
||||
}
|
||||
},
|
||||
info: function() {
|
||||
|
|
@ -132,6 +138,41 @@
|
|||
return function(text, render) {
|
||||
return 'prop-'+render(text).replace('.', '-')
|
||||
}
|
||||
},
|
||||
colspan: function() {
|
||||
return function(text, render) {
|
||||
return this.itemType == 'group' ? 'colspan="2"' : null
|
||||
}
|
||||
},
|
||||
tableClass: function() {
|
||||
return function(text, render) {
|
||||
return fieldsConfig.hasGroups ? 'has-groups' : null
|
||||
}
|
||||
},
|
||||
cellClass: function() {
|
||||
return function(text, render) {
|
||||
var result = this.itemType + ((this.itemType == 'property' && this.groupIndex !== undefined) ? ' grouped' : '')
|
||||
|
||||
if (this.itemType == 'property' && this.groupIndex !== undefined)
|
||||
result += self.groupExpanded(this.group) ? ' expanded' : ' collapsed'
|
||||
|
||||
return result
|
||||
}
|
||||
},
|
||||
expandControl: function() {
|
||||
return function(text, render) {
|
||||
if (this.itemType == 'group') {
|
||||
this.itemStatus = self.groupExpanded(this.title) ? 'expanded' : ''
|
||||
|
||||
return render('<a class="expandControl {{itemStatus}}" href="javascript:;" data-group-index="{{groupIndex}}"><span>Expand/collapse</span></a>', this)
|
||||
}
|
||||
}
|
||||
},
|
||||
dataGroupIndex: function() {
|
||||
return function(text, render) {
|
||||
return this.groupIndex !== undefined && this.itemType == 'property' ? render('data-group-index={{groupIndex}}', this) : ''
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +231,12 @@
|
|||
})
|
||||
|
||||
$('[data-toggle=tooltip]', self.$el.data('oc.popover').$container).tooltip({placement: 'auto right', container: 'body'})
|
||||
|
||||
var $container = self.$el.data('oc.popover').$container
|
||||
$container.on('click', 'tr.group', function(){
|
||||
self.toggleGroup($('a.expandControl', this), $container)
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
var e = $.Event('showing.oc.inspector')
|
||||
|
|
@ -201,6 +248,118 @@
|
|||
displayPopover()
|
||||
}
|
||||
|
||||
// Creates group nodes in the property set
|
||||
//
|
||||
Inspector.prototype.preprocessConfig = function() {
|
||||
var fields = [],
|
||||
result = {
|
||||
hasGroups: false,
|
||||
properties: []
|
||||
},
|
||||
groupIndex = 0
|
||||
|
||||
function findGroup(title) {
|
||||
var groups = $.grep(fields, function(item) {
|
||||
return item.itemType !== undefined && item.itemType == 'group' && item.title == title
|
||||
})
|
||||
|
||||
if (groups.length > 0)
|
||||
return groups[0]
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
$.each(this.config, function() {
|
||||
this.itemType = 'property'
|
||||
|
||||
if (this.group === undefined)
|
||||
fields.push(this)
|
||||
else {
|
||||
var group = findGroup(this.group)
|
||||
|
||||
if (!group) {
|
||||
group = {
|
||||
itemType: 'group',
|
||||
title: this.group,
|
||||
properties: [],
|
||||
groupIndex: groupIndex
|
||||
}
|
||||
|
||||
groupIndex++
|
||||
fields.push(group)
|
||||
}
|
||||
|
||||
this.groupIndex = group.groupIndex
|
||||
group.properties.push(this)
|
||||
}
|
||||
})
|
||||
|
||||
$.each(fields, function() {
|
||||
result.properties.push(this)
|
||||
|
||||
if (this.itemType == 'group') {
|
||||
result.hasGroups = true
|
||||
|
||||
$.each(this.properties, function() {
|
||||
result.properties.push(this)
|
||||
})
|
||||
|
||||
delete this.properties
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Inspector.prototype.toggleGroup = function(link, $container) {
|
||||
var $link = $(link),
|
||||
groupIndex = $link.data('group-index'),
|
||||
propertyRows = $('tr[data-group-index='+groupIndex+']', $container),
|
||||
duration = Math.round(100 / propertyRows.length),
|
||||
collapse = true,
|
||||
statuses = this.loadGroupExpandedStatuses(),
|
||||
title = $('div.title-element', $link.closest('tr')).attr('title')
|
||||
|
||||
if ($link.hasClass('expanded')) {
|
||||
$link.removeClass('expanded')
|
||||
statuses[title] = false
|
||||
} else {
|
||||
$link.addClass('expanded')
|
||||
collapse = false
|
||||
statuses[title] = true
|
||||
}
|
||||
|
||||
propertyRows.each(function(index){
|
||||
var self = $(this)
|
||||
setTimeout(function(){
|
||||
self.toggleClass('collapsed', collapse)
|
||||
self.toggleClass('expanded', !collapse)
|
||||
}, index*duration)
|
||||
|
||||
})
|
||||
|
||||
this.writeGroupExpandedStatuses(statuses)
|
||||
}
|
||||
|
||||
Inspector.prototype.loadGroupExpandedStatuses = function() {
|
||||
var statuses = this.$el.data('inspector-group-statuses')
|
||||
|
||||
return statuses !== undefined ? JSON.parse(statuses) : {}
|
||||
}
|
||||
|
||||
Inspector.prototype.writeGroupExpandedStatuses = function(statuses) {
|
||||
this.$el.data('inspector-group-statuses', JSON.stringify(statuses))
|
||||
}
|
||||
|
||||
Inspector.prototype.groupExpanded = function(title) {
|
||||
var statuses = this.loadGroupExpandedStatuses()
|
||||
|
||||
if (statuses[title] !== undefined)
|
||||
return statuses[title]
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Inspector.prototype.initProperties = function() {
|
||||
var propertyValuesStr = $.trim(this.propertyValuesField.val())
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
tr.group {
|
||||
.user-select(none);
|
||||
|
||||
th {
|
||||
background: #e0e4e5;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
&.collapsed {display: none;}
|
||||
&.expanded {display: table-row;}
|
||||
}
|
||||
|
||||
&.has-groups {
|
||||
th {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
tr.grouped th {
|
||||
padding-left: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
font-weight: 300;
|
||||
border-left: 1px solid @color-inspector-bg;
|
||||
|
|
@ -72,24 +97,66 @@
|
|||
|
||||
> div {
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
span.info {
|
||||
display: inline-block;
|
||||
> div {
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
span.info {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
top: 3px;
|
||||
font-size: 14px;
|
||||
width: 10px;
|
||||
height: 12px;
|
||||
line-height: 80%;
|
||||
.opacity(0.4);
|
||||
&:before {
|
||||
margin-left: 3px;
|
||||
}
|
||||
&:hover {
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.expandControl {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: -6px;
|
||||
top: 3px;
|
||||
font-size: 14px;
|
||||
width: 10px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
line-height: 80%;
|
||||
.opacity(0.4);
|
||||
&:hover {
|
||||
.opacity(1);
|
||||
left: -15px;
|
||||
top: 2px;
|
||||
text-indent: -100000em;
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
||||
&:after {
|
||||
.icon(@angle-right);
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: -2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
font-size: 13px;
|
||||
color: #333333;
|
||||
text-indent: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.expanded span:after {
|
||||
.icon(@angle-down);
|
||||
left: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,9 +277,9 @@ div.control-popover {
|
|||
color: #95a5a6;
|
||||
}
|
||||
|
||||
.select2-input {
|
||||
input.select2-input {
|
||||
min-height: 26px;
|
||||
background: transparent;
|
||||
background: transparent!important;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue